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)
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)
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)
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)
# 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)
-$(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)
-{ don't edit, this file is generated from armins.dat }
+{ don't edit, this file is generated from a64ins.dat }
(
-'nop',
+'none',
'b',
-'cb',
-'tb',
+'cbz',
+'cbnz',
+'tbz',
+'tbnz',
'bl',
'blr',
'br',
'ret',
+'brk',
+'hlt',
+'hvc',
+'smc',
+'svc',
+'eret',
+'dcps1',
+'dcps2',
+'dcps3',
+'drps',
+'dc',
+'at',
+'tlbi',
+'hint',
+'clrex',
+'dsb',
+'dmb',
+'isb',
'ldr',
'str',
+'ldur',
+'stur',
'ldp',
'stp',
'ldnp',
'ldtr',
'sttr',
'ldxr',
+'ldxp',
'stxr',
+'stxp',
'ldar',
'stlr',
'ldaxr',
'stlxr',
+'stlxp',
+'ld1',
+'ld2',
+'ld3',
+'ld4',
+'st1',
+'st2',
+'st3',
+'st4',
+'ld1r',
+'ld2r',
+'ld3r',
+'ld4r',
'prfm',
+'prfum',
'add',
-'adc',
'sub',
-'sbc',
'cmp',
'cmn',
-'mov',
'and',
-'bic',
'eor',
-'eon',
'orr',
'orn',
'tst',
-'mvn',
+'movz',
+'movn',
'movk',
+'mrs',
+'msr',
'adrp',
'adr',
'bfm',
'sbfm',
'ubfm',
'extr',
-'sxt',
-'uxt',
+'adc',
+'sbc',
+'bic',
+'eon',
'asrv',
-'llslv',
+'lslv',
'lsrv',
'rorv',
+'madd',
+'msub',
+'smaddl',
+'smsubl',
+'smulh',
+'umaddl',
+'umsubl',
+'umulh',
+'sdiv',
+'udiv',
'cls',
'clz',
'rbit',
'csneg',
'ccmn',
'ccmp',
-'madd',
-'msub',
-'smaddl',
-'smsubl',
-'smulh',
-'umaddl',
-'umsubl',
-'umulh',
-'sdiv',
-'udiv',
-'neg',
+'nop',
+'yield',
+'wfe',
+'wfi',
+'sev',
+'sevl',
+'mov',
+'bfi',
+'bfxil',
+'sbfiz',
+'sbfx',
+'ubfiz',
+'ubfx',
'asr',
'lsl',
'lsr',
'ror',
-'cset',
-'csetm',
-'cinc',
-'cinv',
-'cneg',
+'sxt',
+'uxt',
+'neg',
'ngc',
+'mvn',
'mneg',
'mul',
'smnegl',
'smull',
'umnegl',
'umull',
+'cset',
+'csetm',
+'cinc',
+'cinv',
+'cneg',
'fmov',
'fcvt',
'fcvtas',
'fcvtzu',
'scvtf',
'ucvtf',
-'fprinta',
-'fprinti',
-'fprintm',
-'fprintn',
-'fprintp',
-'fprintx',
-'fprintz',
+'frinta',
+'frinti',
+'frintm',
+'frintn',
+'frintp',
+'frintx',
+'frintz',
'fabs',
'fneg',
'fsqrt',
'fcmpe',
'fccmp',
'fcmmpe',
-'fcsel'
+'fcsel',
+'umov',
+'ins',
+'movi'
);
-{ 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
);
-[NOP]
+; invalid
+[NONE]
[B]
-[CB]
+[CBZ]
+
+[CBNZ]
-[TB]
+[TBZ]
+
+[TBNZ]
[BL]
[RET]
+[BRK]
+
+[HLT]
+
+[HVC]
+
+[SMC]
+
+[SVC]
+
+[ERET]
+
+[DCPS1]
+
+[DCPS2]
+
+[DCPS3]
+
+[DRPS]
+
+[DC]
+
+[AT]
+
+[TLBI]
+
+[HINT]
+
+[CLREX]
+
+[DSB]
+
+[DMB]
+
+[ISB]
+
[LDR]
[STR]
+[LDUR]
+
+[STUR]
+
[LDP]
[STP]
[LDXR]
+[LDXP]
+
[STXR]
+[STXP]
+
[LDAR]
[STLR]
[STLXR]
+[STLXP]
+
+[LD1]
+
+[LD2]
+
+[LD3]
+
+[LD4]
+
+[ST1]
+
+[ST2]
+
+[ST3]
+
+[ST4]
+
+[LD1R]
+
+[LD2R]
+
+[LD3R]
+
+[LD4R]
+
[PRFM]
-[ADD]
+[PRFUM]
-[ADC]
+[ADD]
[SUB]
-[SBC]
-
[CMP]
[CMN]
-[MOV]
-
[AND]
-[BIC]
-
[EOR]
-[EON]
-
[ORR]
[ORN]
[TST]
-[MVN]
+[MOVZ]
+
+[MOVN]
[MOVK]
+[MRS]
+
+[MSR]
+
[ADRP]
[ADR]
[EXTR]
-[SXT]
+[ADC]
-[UXT]
+[SBC]
+
+[BIC]
+
+[EON]
[ASRV]
-[LLSLV]
+[LSLV]
[LSRV]
[RORV]
+[MADD]
+
+[MSUB]
+
+[SMADDL]
+
+[SMSUBL]
+
+[SMULH]
+
+[UMADDL]
+
+[UMSUBL]
+
+[UMULH]
+
+[SDIV]
+
+[UDIV]
+
[CLS]
[CLZ]
[CCMP]
-[MADD]
+; Aliases
+; they are not generated by the compiler, they are only used for inline assembler
+[NOP]
-[MSUB]
+[YIELD]
-[SMADDL]
+[WFE]
-[SMSUBL]
+[WFI]
-[SMULH]
+[SEV]
-[UMADDL]
+[SEVL]
-[UMSUBL]
+[MOV]
-[UMULH]
+[BFI]
-[SDIV]
+[BFXIL]
-[UDIV]
+[SBFIZ]
-; Aliases
-; they are not generated by the compiler, they are only used for inline assembler
-[NEG]
+[SBFX]
+
+[UBFIZ]
+
+[UBFX]
[ASR]
[ROR]
-[CSET]
-
-[CSETM]
-
-[CINC]
+[SXT]
-[CINV]
+[UXT]
-[CNEG]
+[NEG]
[NGC]
+[MVN]
+
[MNEG]
[MUL]
[UMULL]
+[CSET]
+
+[CSETM]
+
+[CINC]
+
+[CINV]
+
+[CNEG]
+
[FMOV]
[FCVT]
[UCVTF]
-[FPRINTA]
+[FRINTA]
-[FPRINTI]
+[FRINTI]
-[FPRINTM]
+[FRINTM]
-[FPRINTN]
+[FRINTN]
-[FPRINTP]
+[FRINTP]
-[FPRINTX]
+[FRINTX]
-[FPRINTZ]
+[FRINTZ]
[FABS]
[FCSEL]
+[UMOV]
+
+[INS]
+
+[MOVI]
-{ 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,
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,
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,
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,
A_FCMPE,
A_FCCMP,
A_FCMMPE,
-A_FCSEL
+A_FCSEL,
+A_UMOV,
+A_INS,
+A_MOVI
);
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
-{ don't edit, this file is generated from armins.dat }
+{ don't edit, this file is generated from a64ins.dat }
(
);
{
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
pinsentry=^tinsentry;
-{ const
- InsTab : array[0..instabentries-1] of TInsEntry={$i a64tab.inc} }
-
var
InsTabCache : PInsTabCache;
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);
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);
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
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;
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
*****************************************************************************}
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);
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);
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);
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;
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
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;
{ we need to reset everything here, because the choosen insentry
can be invalid for a new situation where the previously optimized
insentry is not correct }
- InsEntry:=nil;
- InsSize:=0;
- LastInsOffset:=-1;
end;
procedure taicpu.ResetPass2;
begin
{ we are here in a second pass, check if the instruction can be optimized }
- if assigned(InsEntry) and
- ((InsEntry^.flags and IF_PASS2)<>0) then
- begin
- InsEntry:=nil;
- InsSize:=0;
- end;
- LastInsOffset:=-1;
end;
function taicpu.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;
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.
--- /dev/null
+{
+ 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.
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.
--- /dev/null
+{
+ 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.
{
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
{ 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;
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;
{$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
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
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'
);
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);
shiftimm : byte;
end;
- tcpumodeflag = (mfA, mfI, mfF);
- tcpumodeflags = set of tcpumodeflag;
-
- tspecialregflag = (srC, srX, srS, srF);
- tspecialregflags = set of tspecialregflag;
-
{*****************************************************************************
Constants
*****************************************************************************}
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
*****************************************************************************}
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
function dwarf_reg(r:tregister):shortint;
+ function is_shifter_const(d: aint; size: tcgsize): boolean;
+
+
implementation
uses
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;
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;
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;
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
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
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.
{ 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
--- /dev/null
+{******************************************************************************
+ 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.
{
- Copyright (c) 2003-2012 by Florian Klaempfl and others
+ Copyright (c) 2013-2014 by Jonas Maebe, Florian Klaempfl and others
AArch64 specific calling conventions
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
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
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
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:
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 }
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
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 :
end;
- function taarch64paramanager.ret_in_param(def:tdef;pd:tabstractprocdef):boolean;
- var
- i: longint;
- sym: tsym;
- fpufield: boolean;
+ function taarch64paramanager.ret_in_param(def: tdef; pd: tabstractprocdef): boolean;
begin
if handle_common_ret_in_param(def,pd,result) then
exit;
- case def.typ of
- recorddef:
- begin
- result:=def.size>4;
- if not result and
- (target_info.abi in [abi_default,abi_armeb]) then
- begin
- { in case of the old ARM abi (APCS), a struct is returned in
- a register only if it is simple. And what is a (non-)simple
- struct:
-
- "A non-simple type is any non-floating-point type of size
- greater than one word (including structures containing only
- floating-point fields), and certain single-word structured
- types."
- (-- ARM APCS documentation)
-
- So only floating point types or more than one word ->
- definitely non-simple (more than one word is already
- checked above). This includes unions/variant records with
- overlaid floating point and integer fields.
-
- Smaller than one word struct types are simple if they are
- "integer-like", and:
-
- "A structure is termed integer-like if its size is less than
- or equal to one word, and the offset of each of its
- addressable subfields is zero."
- (-- ARM APCS documentation)
-
- An "addressable subfield" is a field of which you can take
- the address, which in practive means any non-bitfield.
- In Pascal, there is no way to express the difference that
- you can have in C between "char" and "int :8". In this
- context, we use the fake distinction that a type defined
- inside the record itself (such as "a: 0..255;") indicates
- a bitpacked field while a field using a different type
- (such as "a: byte;") is not.
- }
- for i:=0 to trecorddef(def).symtable.SymList.count-1 do
- begin
- sym:=tsym(trecorddef(def).symtable.SymList[i]);
- if sym.typ<>fieldvarsym then
- continue;
- { bitfield -> ignore }
- if (trecordsymtable(trecorddef(def).symtable).usefieldalignment=bit_alignment) and
- (tfieldvarsym(sym).vardef.typ in [orddef,enumdef]) and
- (tfieldvarsym(sym).vardef.owner.defowner=def) then
- continue;
- { all other fields must be at offset zero }
- if tfieldvarsym(sym).fieldoffset<>0 then
- begin
- result:=true;
- exit;
- end;
- { floating point field -> also by reference }
- if tfieldvarsym(sym).vardef.typ=floatdef then
- begin
- result:=true;
- exit;
- end;
- end;
- end;
- end;
- procvardef:
- if not tprocvardef(def).is_addressonly then
- result:=true
- else
- result:=false
- else
- result:=inherited ret_in_param(def,pd);
- end;
- end;
-
-
- procedure taarch64paramanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister);
- begin
- curintreg:=RS_R0;
- curfloatreg:=RS_F0;
- curmmreg:=RS_D0;
- cur_stack_offset:=0;
- sparesinglereg := NR_NO;
+ { ABI: if the parameter would be passed in registers, it is returned
+ in those registers; otherwise, it's returned by reference }
+ result:=push_addr_param(vs_value,def,pd.proccalloption);
end;
- function taarch64paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
- var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword; var sparesinglereg: tregister; isvariadic: boolean):longint;
-
+ procedure taarch64paramanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist; isvariadic: boolean);
var
- nextintreg,nextfloatreg,nextmmreg : tsuperregister;
- paradef : tdef;
- paraloc : pcgparalocation;
- stack_offset : aword;
- hp : tparavarsym;
- loc : tcgloc;
- paracgsize : tcgsize;
- paralen : longint;
- i : integer;
- firstparaloc: boolean;
-
- procedure assignintreg;
- begin
- { In case of po_delphi_nested_cc, the parent frame pointer
- is always passed on the stack. }
- if (nextintreg<=RS_R3) and
- (not(vo_is_parentfp in hp.varoptions) or
- not(po_delphi_nested_cc in p.procoptions)) then
- begin
- paraloc^.loc:=LOC_REGISTER;
- paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
- inc(nextintreg);
- end
- else
- begin
- paraloc^.loc:=LOC_REFERENCE;
- paraloc^.reference.index:=NR_STACK_POINTER_REG;
- paraloc^.reference.offset:=stack_offset;
- inc(stack_offset,4);
- end;
- end;
-
-
+ hp: tparavarsym;
+ i: longint;
begin
- result:=0;
- nextintreg:=curintreg;
- nextfloatreg:=curfloatreg;
- nextmmreg:=curmmreg;
- stack_offset:=cur_stack_offset;
-
for i:=0 to paras.count-1 do
begin
hp:=tparavarsym(paras[i]);
- paradef:=hp.vardef;
-
- hp.paraloc[side].reset;
-
- { currently only support C-style array of const,
- there should be no location assigned to the vararg array itself }
- if (p.proccalloption in cstylearrayofconst) and
- is_array_of_const(paradef) then
- begin
- paraloc:=hp.paraloc[side].add_location;
- { hack: the paraloc must be valid, but is not actually used }
- paraloc^.loc:=LOC_REGISTER;
- paraloc^.register:=NR_R0;
- paraloc^.size:=OS_ADDR;
- break;
- end;
-
- if push_addr_param(hp.varspez,paradef,p.proccalloption) then
+ { hidden function result parameter is passed in X8 (doesn't have to
+ be valid on return) according to the ABI
+
+ -- don't follow the ABI for managed types, because
+ a) they are passed in registers as parameters, so we should also
+ return them in a register to be ABI-compliant (which we can't
+ because the entire compiler is built around the idea that
+ they are returned by reference, for ref-counting performance
+ and Delphi-compatibility reasons)
+ b) there are hacks in the system unit that expect that you can
+ call
+ function f: com_interface;
+ as
+ procedure p(out o: obj);
+ That can only work in case we do not use x8 to return them
+ from the function, but the regular first parameter register.
+
+ As the ABI says this behaviour is ok for C++ classes with a
+ non-trivial copy constructor or destructor, it seems reasonable
+ for us to do this for managed types as well.}
+ if (vo_is_funcret in hp.varoptions) and
+ not is_managed_type(hp.vardef) then
begin
- paradef:=getpointerdef(paradef);
- loc:=LOC_REGISTER;
- paracgsize := OS_ADDR;
- paralen := tcgsize2size[OS_ADDR];
- end
- else
- begin
- if not is_special_array(paradef) then
- paralen := paradef.size
- else
- paralen := tcgsize2size[def_cgsize(paradef)];
- loc := getparaloc(p.proccalloption,paradef,isvariadic);
- if (paradef.typ in [objectdef,arraydef,recorddef]) and
- not is_special_array(paradef) and
- (hp.varspez in [vs_value,vs_const]) then
- paracgsize := int_cgsize(paralen)
- else
+ hp.paraloc[side].reset;
+ hp.paraloc[side].size:=OS_ADDR;
+ hp.paraloc[side].alignment:=voidpointertype.alignment;
+ hp.paraloc[side].intsize:=voidpointertype.size;
+ hp.paraloc[side].def:=getpointerdef(hp.vardef);
+ with hp.paraloc[side].add_location^ do
begin
- paracgsize:=def_cgsize(paradef);
- { for things like formaldef }
- if (paracgsize=OS_NO) then
- begin
- paracgsize:=OS_ADDR;
- paralen:=tcgsize2size[OS_ADDR];
- paradef:=voidpointertype;
- end;
+ size:=OS_ADDR;
+ def:=hp.paraloc[side].def;
+ loc:=LOC_REGISTER;
+ register:=NR_X8;
end
- end;
-
- hp.paraloc[side].size:=paracgsize;
- hp.paraloc[side].Alignment:=std_param_align;
- hp.paraloc[side].intsize:=paralen;
- hp.paraloc[side].def:=paradef;
- firstparaloc:=true;
-
-{$ifdef EXTDEBUG}
- if paralen=0 then
- internalerror(200410311);
-{$endif EXTDEBUG}
- while paralen>0 do
- begin
- paraloc:=hp.paraloc[side].add_location;
-
- if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
- case paracgsize of
- OS_F32:
- paraloc^.size:=OS_32;
- OS_F64:
- paraloc^.size:=OS_32;
- else
- internalerror(2005082901);
- end
- else if (paracgsize in [OS_NO,OS_64,OS_S64]) then
- paraloc^.size := OS_32
- else
- paraloc^.size:=paracgsize;
- case loc of
- LOC_REGISTER:
- begin
- { align registers for eabi }
- if (target_info.abi in [abi_eabi,abi_eabihf]) and
- firstparaloc and
- (paradef.alignment=8) then
- begin
- if (nextintreg in [RS_R1,RS_R3]) then
- inc(nextintreg)
- else if nextintreg>RS_R3 then
- stack_offset:=align(stack_offset,8);
- end;
- { this is not abi compliant
- why? (FK) }
- if nextintreg<=RS_R3 then
- begin
- paraloc^.loc:=LOC_REGISTER;
- paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBWHOLE);
- inc(nextintreg);
- end
- else
- begin
- { LOC_REFERENCE always contains everything that's left }
- paraloc^.loc:=LOC_REFERENCE;
- paraloc^.size:=int_cgsize(paralen);
- if (side=callerside) then
- paraloc^.reference.index:=NR_STACK_POINTER_REG;
- paraloc^.reference.offset:=stack_offset;
- inc(stack_offset,align(paralen,4));
- paralen:=0;
- end;
- end;
- LOC_FPUREGISTER:
- begin
- if nextfloatreg<=RS_F3 then
- begin
- paraloc^.loc:=LOC_FPUREGISTER;
- paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
- inc(nextfloatreg);
- end
- else
- begin
- paraloc^.loc:=LOC_REFERENCE;
- paraloc^.reference.index:=NR_STACK_POINTER_REG;
- paraloc^.reference.offset:=stack_offset;
- case paraloc^.size of
- OS_F32:
- inc(stack_offset,4);
- OS_F64:
- inc(stack_offset,8);
- OS_F80:
- inc(stack_offset,10);
- OS_F128:
- inc(stack_offset,16);
- else
- internalerror(200403201);
- end;
- end;
- end;
- LOC_MMREGISTER:
- begin
- if (nextmmreg<=RS_D7) or
- ((paraloc^.size = OS_F32) and
- (sparesinglereg<>NR_NO)) then
- begin
- paraloc^.loc:=LOC_MMREGISTER;
- case paraloc^.size of
- OS_F32:
- if sparesinglereg = NR_NO then
- begin
- paraloc^.register:=newreg(R_MMREGISTER,nextmmreg,R_SUBFS);
- sparesinglereg:=newreg(R_MMREGISTER,nextmmreg-RS_S0+RS_S1,R_SUBFS);
- inc(nextmmreg);
- end
- else
- begin
- paraloc^.register:=sparesinglereg;
- sparesinglereg := NR_NO;
- end;
- OS_F64:
- begin
- paraloc^.register:=newreg(R_MMREGISTER,nextmmreg,R_SUBFD);
- inc(nextmmreg);
- end;
- else
- internalerror(2012031601);
- end;
- end
- else
- begin
- { once a floating point parameters has been placed
- on the stack we must not pass any more in vfp regs
- even if there is a single precision register still
- free}
- sparesinglereg := NR_NO;
- { LOC_REFERENCE always contains everything that's left }
- paraloc^.loc:=LOC_REFERENCE;
- paraloc^.size:=int_cgsize(paralen);
- if (side=callerside) then
- paraloc^.reference.index:=NR_STACK_POINTER_REG;
- paraloc^.reference.offset:=stack_offset;
- inc(stack_offset,align(paralen,4));
- paralen:=0;
- end;
- end;
- LOC_REFERENCE:
- begin
- if push_addr_param(hp.varspez,paradef,p.proccalloption) then
- begin
- paraloc^.size:=OS_ADDR;
- assignintreg
- end
- else
- begin
- { align stack for eabi }
- if (target_info.abi in [abi_eabi,abi_eabihf]) and
- firstparaloc and
- (paradef.alignment=8) then
- stack_offset:=align(stack_offset,8);
-
- paraloc^.size:=paracgsize;
- paraloc^.loc:=LOC_REFERENCE;
- paraloc^.reference.index:=NR_STACK_POINTER_REG;
- paraloc^.reference.offset:=stack_offset;
- inc(stack_offset,align(paralen,4));
- paralen:=0
- end;
- end;
- else
- internalerror(2002071002);
- end;
- if side=calleeside then
- begin
- if paraloc^.loc=LOC_REFERENCE then
- begin
- paraloc^.reference.index:=NR_FRAME_POINTER_REG;
- { on non-Darwin, the framepointer contains the value
- of the stack pointer on entry. On Darwin, the
- framepointer points to the previously saved
- framepointer (which is followed only by the saved
- return address -> framepointer + 4 = stack pointer
- on entry }
- if not(target_info.system in systems_darwin) then
- inc(paraloc^.reference.offset,4)
- else
- inc(paraloc^.reference.offset,8);
- end;
- end;
- dec(paralen,tcgsize2size[paraloc^.size]);
- firstparaloc:=false
- end;
+ end
+ else
+ alloc_para(hp.paraloc[side],p,hp.varspez,side,hp.vardef,isvariadic,
+ (vo_is_parentfp in hp.varoptions) and
+ (po_delphi_nested_cc in p.procoptions));
end;
- curintreg:=nextintreg;
- curfloatreg:=nextfloatreg;
- curmmreg:=nextmmreg;
- cur_stack_offset:=stack_offset;
- result:=cur_stack_offset;
end;
function taarch64paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
var
- paraloc : pcgparalocation;
- retcgsize : tcgsize;
+ retcgsize: tcgsize;
begin
if set_common_funcretloc_info(p,forcetempdef,retcgsize,result) then
exit;
- paraloc:=result.add_location;
- { Return in FPU register? }
- if result.def.typ=floatdef then
+ { in this case, it must be returned in registers as if it were passed
+ as the first parameter }
+ init_para_alloc_values;
+ alloc_para(result,p,vs_value,side,result.def,false,false);
+ { sanity check (LOC_VOID for empty records) }
+ if not assigned(result.location) or
+ not(result.location^.loc in [LOC_REGISTER,LOC_MMREGISTER,LOC_VOID]) then
+ internalerror(2014113001);
+ end;
+
+ function taarch64paramanager.param_use_paraloc(const cgpara: tcgpara): boolean;
+ begin
+ { we always set up a stack frame -> we can always access the parameters
+ this way }
+ result:=
+ (cgpara.location^.loc=LOC_REFERENCE) and
+ not assigned(cgpara.location^.next);
+ end;
+
+
+ procedure taarch64paramanager.init_para_alloc_values;
+ begin
+ curintreg:=RS_FIRST_INT_PARAM_SUPREG;
+ curmmreg:=RS_FIRST_MM_PARAM_SUPREG;
+ curstackoffset:=0;
+ end;
+
+
+ procedure taarch64paramanager.alloc_para(out result: tcgpara; p: tabstractprocdef; varspez: tvarspez; side: tcallercallee; paradef: tdef; isvariadic, isdelphinestedcc: boolean);
+ var
+ hfabasedef, locdef: tdef;
+ paraloc: pcgparalocation;
+ paralen, stackslotlen: asizeint;
+ loc: tcgloc;
+ paracgsize, locsize: tcgsize;
+ firstparaloc: boolean;
+ begin
+ result.reset;
+
+ { currently only support C-style array of const,
+ there should be no location assigned to the vararg array itself }
+ if (p.proccalloption in cstylearrayofconst) and
+ is_array_of_const(paradef) then
begin
- if target_info.abi = abi_eabihf then
- begin
- paraloc^.loc:=LOC_MMREGISTER;
- case retcgsize of
- OS_64,
- OS_F64:
- begin
- paraloc^.register:=NR_MM_RESULT_REG;
- end;
- OS_32,
- OS_F32:
- begin
- paraloc^.register:=NR_S0;
- end;
- else
- internalerror(2012032501);
- end;
- paraloc^.size:=retcgsize;
- end
- else if (p.proccalloption in [pocall_softfloat]) or
- (cs_fp_emulation in current_settings.moduleswitches) or
- (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3,fpu_vfpv3_d16,fpu_fpv4_s16]) then
- begin
- case retcgsize of
- OS_64,
- OS_F64:
- begin
- paraloc^.loc:=LOC_REGISTER;
- if target_info.endian = endian_big then
- paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
- else
- paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
- paraloc^.size:=OS_32;
- paraloc:=result.add_location;
- paraloc^.loc:=LOC_REGISTER;
- if target_info.endian = endian_big then
- paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
- else
- paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
- paraloc^.size:=OS_32;
- end;
- OS_32,
- OS_F32:
- begin
- paraloc^.loc:=LOC_REGISTER;
- paraloc^.register:=NR_FUNCTION_RETURN_REG;
- paraloc^.size:=OS_32;
- end;
- else
- internalerror(2005082603);
- end;
- end
- else
- begin
- paraloc^.loc:=LOC_FPUREGISTER;
- paraloc^.register:=NR_FPU_RESULT_REG;
- paraloc^.size:=retcgsize;
- end;
+ paraloc:=result.add_location;
+ { hack: the paraloc must be valid, but is not actually used }
+ paraloc^.loc:=LOC_REGISTER;
+ paraloc^.register:=NR_X0;
+ paraloc^.size:=OS_ADDR;
+ exit;
+ end;
+
+ if push_addr_param(varspez,paradef,p.proccalloption) then
+ begin
+ paradef:=getpointerdef(paradef);
+ loc:=LOC_REGISTER;
+ paracgsize:=OS_ADDR;
+ paralen:=tcgsize2size[OS_ADDR];
end
- { Return in register }
else
begin
- if retcgsize in [OS_64,OS_S64] then
- begin
- paraloc^.loc:=LOC_REGISTER;
- if target_info.endian = endian_big then
- paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
- else
- paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
- paraloc^.size:=OS_32;
- paraloc:=result.add_location;
- paraloc^.loc:=LOC_REGISTER;
- if target_info.endian = endian_big then
- paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
- else
- paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
- paraloc^.size:=OS_32;
- end
+ if not is_special_array(paradef) then
+ paralen:=paradef.size
+ else
+ paralen:=tcgsize2size[def_cgsize(paradef)];
+ loc:=getparaloc(p.proccalloption,paradef);
+ if (paradef.typ in [objectdef,arraydef,recorddef]) and
+ not is_special_array(paradef) and
+ (varspez in [vs_value,vs_const]) then
+ paracgsize:=int_cgsize(paralen)
else
begin
- paraloc^.loc:=LOC_REGISTER;
- paraloc^.register:=NR_FUNCTION_RETURN_REG;
- if (result.intsize<>3) then
- paraloc^.size:=retcgsize
- else
- paraloc^.size:=OS_32;
- end;
+ paracgsize:=def_cgsize(paradef);
+ { for things like formaldef }
+ if paracgsize=OS_NO then
+ begin
+ paracgsize:=OS_ADDR;
+ paralen:=tcgsize2size[OS_ADDR];
+ paradef:=voidpointertype;
+ end;
+ end
end;
+
+ { get hfa basedef if applicable }
+ if not is_hfa(paradef,hfabasedef) then
+ hfabasedef:=nil;
+
+ result.size:=paracgsize;
+ result.alignment:=std_param_align;
+ result.intsize:=paralen;
+ result.def:=paradef;
+
+ { empty record: skipped (explicitly defined by Apple ABI, undefined
+ by general ABI; libffi also skips them in all cases) }
+ if not is_special_array(paradef) and
+ (paradef.size=0) then
+ begin
+ paraloc:=result.add_location;
+ paraloc^.loc:=LOC_VOID;
+ paraloc^.def:=paradef;
+ paraloc^.size:=OS_NO;
+ exit;
+ end;
+
+ { sufficient registers left? }
+ case loc of
+ LOC_REGISTER:
+ begin
+ { In case of po_delphi_nested_cc, the parent frame pointer
+ is always passed on the stack. }
+ if isdelphinestedcc then
+ loc:=LOC_REFERENCE
+ else if curintreg+((paralen-1) shr 3)>RS_LAST_INT_PARAM_SUPREG then
+ begin
+ {Â not enough integer registers left -> no more register
+ parameters, copy all to stack
+ }
+ curintreg:=succ(RS_LAST_INT_PARAM_SUPREG);
+ loc:=LOC_REFERENCE;
+ end;
+ end;
+ LOC_MMREGISTER:
+ begin;
+ { every hfa element must be passed in a separate register }
+ if (assigned(hfabasedef) and
+ (curmmreg+(paralen div hfabasedef.size)>RS_LAST_MM_PARAM_SUPREG)) or
+ (curmmreg+((paralen-1) shr 3)>RS_LAST_MM_PARAM_SUPREG) then
+ begin
+ {Â not enough mm registers left -> no more register
+ parameters, copy all to stack
+ }
+ curmmreg:=succ(RS_LAST_MM_PARAM_SUPREG);
+ loc:=LOC_REFERENCE;
+ end;
+ end;
+ end;
+
+ { allocate registers/stack locations }
+ firstparaloc:=true;
+ repeat
+ paraloc:=result.add_location;
+
+ { set paraloc size/def }
+ if assigned(hfabasedef) then
+ begin
+ locsize:=def_cgsize(hfabasedef);
+ locdef:=hfabasedef;
+ end
+ { make sure we don't lose whether or not the type is signed }
+ else if (loc=LOC_REGISTER) and
+ (paradef.typ<>orddef) then
+ begin
+ locsize:=int_cgsize(paralen);
+ locdef:=get_paraloc_def(paradef,paralen,firstparaloc);
+ end
+ else
+ begin
+ locsize:=paracgsize;
+ locdef:=paradef;
+ end;
+ if locsize in [OS_NO,OS_128,OS_S128] then
+ begin
+ if paralen>4 then
+ begin
+ paraloc^.size:=OS_INT;
+ paraloc^.def:=u64inttype;
+ end
+ else
+ begin
+ { for 3-byte records }
+ paraloc^.size:=OS_32;
+ paraloc^.def:=u32inttype;
+ end;
+ end
+ else
+ begin
+ paraloc^.size:=locsize;
+ paraloc^.def:=locdef;
+ end;
+
+ { paraloc loc }
+ paraloc^.loc:=loc;
+
+ { assign register/stack address }
+ case loc of
+ LOC_REGISTER:
+ begin
+ paraloc^.register:=newreg(R_INTREGISTER,curintreg,cgsize2subreg(R_INTREGISTER,paraloc^.size));
+ inc(curintreg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+
+ { "The general ABI specifies that it is the callee's
+ responsibility to sign or zero-extend arguments having fewer
+ than 32 bits, and that unused bits in a register are
+ unspecified. In iOS, however, the caller must perform such
+ extensions, up to 32 bits." }
+ if (target_info.abi=abi_aarch64_darwin) and
+ (side=callerside) and
+ is_ordinal(paradef) and
+ (paradef.size<4) then
+ paraloc^.size:=OS_32;
+
+ { in case it's a composite, "The argument is passed as though
+ it had been loaded into the registers from a double-word-
+ aligned address with an appropriate sequence of LDR
+ instructions loading consecutive registers from memory" ->
+ in case of big endian, values in not completely filled
+ registers must be shifted to the top bits }
+ if (target_info.endian=endian_big) and
+ not(paraloc^.size in [OS_64,OS_S64]) and
+ (paradef.typ in [setdef,recorddef,arraydef,objectdef]) then
+ paraloc^.shiftval:=-(8-tcgsize2size[paraloc^.size]);
+ end;
+ LOC_MMREGISTER:
+ begin
+ paraloc^.register:=newreg(R_MMREGISTER,curmmreg,cgsize2subreg(R_MMREGISTER,paraloc^.size));
+ inc(curmmreg);
+ dec(paralen,tcgsize2size[paraloc^.size]);
+ end;
+ LOC_REFERENCE:
+ begin
+ paraloc^.size:=paracgsize;
+ paraloc^.loc:=LOC_REFERENCE;
+
+ { the current stack offset may not be properly aligned in
+ case we're on Darwin have allocated a non-variadic argument
+ < 8 bytes previously }
+ if target_info.abi=abi_aarch64_darwin then
+ curstackoffset:=align(curstackoffset,paraloc^.def.alignment);
+
+ { on Darwin, non-variadic arguments take up their actual size
+ on the stack; on other platforms, they take up a multiple of
+ 8 bytes }
+ if (target_info.abi=abi_aarch64_darwin) and
+ not isvariadic then
+ stackslotlen:=paralen
+ else
+ stackslotlen:=align(paralen,8);
+
+ { from the ABI: if arguments occupy partial stack space, they
+ have to occupy the lowest significant bits of a register
+ containing that value which is then stored to memory ->
+ in case of big endian, skip the alignment bytes (if any) }
+ if target_info.endian=endian_little then
+ paraloc^.reference.offset:=curstackoffset
+ else
+ paraloc^.reference.offset:=curstackoffset+stackslotlen-paralen;
+ if side=callerside then
+ paraloc^.reference.index:=NR_STACK_POINTER_REG
+ else
+ begin
+ paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+ inc(paraloc^.reference.offset,16);
+ end;
+ inc(curstackoffset,stackslotlen);
+ paralen:=0
+ end;
+ else
+ internalerror(2002071002);
+ end;
+ firstparaloc:=false;
+ { <=0 for sign/zero-extended locations }
+ until paralen<=0;
end;
- function taarch64paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
- var
- cur_stack_offset: aword;
- curintreg, curfloatreg, curmmreg: tsuperregister;
- sparesinglereg:tregister;
+ function taarch64paramanager.create_paraloc_info(p: tabstractprocdef; side: tcallercallee):longint;
begin
- init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
+ init_para_alloc_values;
- result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,false);
+ create_paraloc_info_intern(p,side,p.paras,false);
+ result:=curstackoffset;
create_funcretloc_info(p,side);
end;
- function taarch64paramanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;
- var
- cur_stack_offset: aword;
- curintreg, curfloatreg, curmmreg: tsuperregister;
- sparesinglereg:tregister;
+ function taarch64paramanager.create_varargs_paraloc_info(p: tabstractprocdef; varargspara: tvarargsparalist):longint;
begin
- init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg);
+ init_para_alloc_values;
- result:=create_paraloc_info_intern(p,callerside,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true);
- if (p.proccalloption in cstylearrayofconst) then
- { just continue loading the parameters in the registers }
- result:=create_paraloc_info_intern(p,callerside,varargspara,curintreg,curfloatreg,curmmreg,cur_stack_offset,sparesinglereg,true)
+ { non-variadic parameters }
+ create_paraloc_info_intern(p,callerside,p.paras,false);
+ if p.proccalloption in cstylearrayofconst then
+ begin
+ { on Darwin, we cannot use any registers for variadic parameters }
+ if target_info.abi=abi_aarch64_darwin then
+ begin
+ curintreg:=succ(RS_LAST_INT_PARAM_SUPREG);
+ curmmreg:=succ(RS_LAST_MM_PARAM_SUPREG);
+ end;
+ { continue loading the parameters }
+ create_paraloc_info_intern(p,callerside,varargspara,true);
+ result:=curstackoffset;
+ end
else
internalerror(200410231);
end;
--- /dev/null
+{
+ 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.
--- /dev/null
+{
+ 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.
--- /dev/null
+{
+ 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.
--- /dev/null
+{
+ 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.
--- /dev/null
+{
+ 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.
--- /dev/null
+{
+ 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.
--- /dev/null
+{
+ 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.
--- /dev/null
+{
+ 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.
--- /dev/null
+{
+ 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.
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);
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);
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
{ don't edit, this file is generated from a64reg.dat }
-226
+231
tregister($0105001E),
tregister($0104001F),
tregister($0105001F),
+tregister($01040020),
+tregister($01050020),
tregister($04010000),
tregister($04030000),
tregister($04090000),
tregister($0409001F),
tregister($040a001F),
tregister($0405001F),
-tregister($05000000)
+tregister($05000000),
+tregister($05000001),
+tregister($05000002),
+tregister($05000003)
59,
61,
63,
+65,
2,
4,
6,
60,
62,
64,
-65,
-70,
-75,
-80,
-85,
-90,
-95,
-100,
-105,
-110,
-115,
-120,
-125,
-130,
-135,
-140,
-145,
-150,
-155,
-160,
-165,
-170,
-175,
-180,
-185,
-190,
-195,
-200,
-205,
-210,
-215,
-220,
66,
-71,
-76,
-81,
-86,
-91,
-96,
-101,
-106,
-111,
-116,
-121,
-126,
-131,
-136,
-141,
-146,
-151,
-156,
-161,
-166,
-171,
-176,
-181,
-186,
-191,
-196,
-201,
-206,
-211,
-216,
-221,
-69,
-74,
-79,
-84,
-89,
-94,
-99,
-104,
-109,
-114,
-119,
-124,
-129,
-134,
-139,
-144,
-149,
-154,
-159,
-164,
-169,
-174,
-179,
-184,
-189,
-194,
-199,
-204,
-209,
-214,
-219,
-224,
67,
72,
77,
213,
218,
223,
-225
+71,
+76,
+81,
+86,
+91,
+96,
+101,
+106,
+111,
+116,
+121,
+126,
+131,
+136,
+141,
+146,
+151,
+156,
+161,
+166,
+171,
+176,
+181,
+186,
+191,
+196,
+201,
+206,
+211,
+216,
+221,
+226,
+69,
+74,
+79,
+84,
+89,
+94,
+99,
+104,
+109,
+114,
+119,
+124,
+129,
+134,
+139,
+144,
+149,
+154,
+159,
+164,
+169,
+174,
+179,
+184,
+189,
+194,
+199,
+204,
+209,
+214,
+219,
+224,
+70,
+75,
+80,
+85,
+90,
+95,
+100,
+105,
+110,
+115,
+120,
+125,
+130,
+135,
+140,
+145,
+150,
+155,
+160,
+165,
+170,
+175,
+180,
+185,
+190,
+195,
+200,
+205,
+210,
+215,
+220,
+225,
+227,
+228,
+229,
+230
{ 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,
150,
155,
160,
-75,
165,
+80,
170,
175,
180,
200,
205,
210,
-80,
215,
-220,
85,
+220,
+225,
90,
95,
100,
105,
110,
+115,
+228,
+229,
68,
73,
118,
103,
108,
113,
-66,
+227,
71,
-116,
+76,
121,
126,
131,
151,
156,
161,
-76,
166,
+81,
171,
176,
181,
201,
206,
211,
-81,
216,
-221,
86,
+221,
+226,
91,
96,
101,
106,
111,
-225,
+116,
69,
74,
119,
104,
109,
114,
-67,
-72,
-117,
-122,
-127,
-132,
-137,
-142,
-147,
-152,
-157,
-162,
-77,
-167,
-172,
-177,
-182,
-187,
-192,
-197,
-202,
-207,
-212,
-82,
-217,
-222,
-87,
-92,
-97,
-102,
-107,
-112,
+66,
+230,
1,
3,
21,
15,
17,
19,
+65,
63,
2,
4,
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
'x30',
'wzr',
'xzr',
+'wsp',
+'sp',
'b0',
'h0',
's0',
's31',
'd31',
'q31',
-'nzcv'
+'nzcv',
+'fpcr',
+'fpsr',
+'tpidr_el0'
RS_X30 = $1E;
RS_WZR = $1F;
RS_XZR = $1F;
+RS_WSP = $20;
+RS_SP = $20;
RS_B0 = $00;
RS_H0 = $00;
RS_S0 = $00;
RS_D31 = $1F;
RS_Q31 = $1F;
RS_NZCV = $00;
+RS_FPCR = $01;
+RS_FPSR = $02;
+RS_TPIDR_EL0 = $03;
--- /dev/null
+{
+ 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.
--- /dev/null
+{
+ 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.
--- /dev/null
+{
+ 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.
ait_labeled_instruction,
{$endif m68k}
{$ifdef arm}
- ait_thumb_func,
ait_thumb_set,
{$endif arm}
ait_set,
'labeled_instr',
{$endif m68k}
{$ifdef arm}
- 'thumb_func',
'thumb_set',
{$endif arm}
'set',
{$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}
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);
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,
{ 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=(
{ 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',
{$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;
system_powerpc64_darwin,
system_x86_64_darwin,
system_arm_darwin,
+ system_aarch64_darwin,
+ system_x86_64_iphonesim,
system_powerpc_aix,
system_powerpc64_aix:
begin
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;
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^);
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}
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;
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;
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);
aasmbase,aasmtai,aasmdata,aasmsym,
ogbase,
symtype,
- cpubase,cpuinfo,cgbase,cgutils;
+ cpubase,cpuinfo,cgbase,cgutils,
+ sysutils;
const
{ "mov reg,reg" source operand number }
$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 }
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;
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;
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 }
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);
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;
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;
{ 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;
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
function spilling_create_load(const ref:treference;r:tregister):Taicpu;
- var
- op: tasmop;
begin
case getregtype(r) of
R_INTREGISTER :
}
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;
function spilling_create_store(r:tregister; const ref:treference):Taicpu;
- var
- op: tasmop;
begin
case getregtype(r) of
R_INTREGISTER :
}
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;
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;
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;
else
if (ot and OT_FPUREG)=OT_FPUREG then
s:=s+'fpureg'
+ else
+ if (ot and OT_REGS)=OT_REGS then
+ s:=s+'sreg'
+ else
+ if (ot and OT_REGF)=OT_REGF then
+ s:=s+'creg'
else
if (ot and OT_REGISTER)=OT_REGISTER then
begin
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
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]
{ 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
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 }
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;
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
(
(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
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
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;
{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
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
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;
{ 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;
{ 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;
// ldr,str,ldrb,strb
#$17,
// stm,ldm
- #$26
+ #$26,#$69,#$8C,
+ // vldm/vstm
+ #$44,#$94
]) then
begin
Matches:=0;
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
begin
{ create the .ot fields }
create_ot(objdata);
+
+ BuildArmMasks;
{ set the file postion }
current_filepos:=fileinfo;
end
procedure taicpu.gencode(objdata:TObjData);
+ const
+ CondVal : array[TAsmCond] of byte=(
+ $E, $0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $A,
+ $B, $C, $D, $E, 0);
var
- bytes : dword;
+ bytes, rd, rm, rn, d, m, n : dword;
+ bytelen : longint;
+ dp_operation : boolean;
i_field : byte;
+ currsym : TObjSymbol;
+ offset : longint;
+ refoper : poper;
+ msb : longint;
+ r: byte;
procedure setshifterop(op : byte);
+ var
+ r : byte;
+ imm : dword;
+ count : integer;
begin
case oper[op]^.typ of
top_const:
begin
i_field:=1;
- bytes:=bytes or dword(oper[op]^.val and $fff);
+ if oper[op]^.val and $ff=oper[op]^.val then
+ bytes:=bytes or dword(oper[op]^.val)
+ else
+ begin
+ { calc rotate and adjust imm }
+ count:=0;
+ r:=0;
+ imm:=dword(oper[op]^.val);
+ repeat
+ imm:=RolDWord(imm, 2);
+ inc(r);
+ inc(count);
+ if count > 32 then
+ begin
+ message1(asmw_e_invalid_opcode_and_operands, 'invalid shifter imm');
+ exit;
+ end;
+ until (imm and $ff)=imm;
+ bytes:=bytes or (r shl 8) or imm;
+ end;
end;
top_reg:
begin
i_field:=0;
- bytes:=bytes or (getsupreg(oper[op]^.reg) shl 16);
+ bytes:=bytes or getsupreg(oper[op]^.reg);
{ does a real shifter op follow? }
- if (op+1<=op) and (oper[op+1]^.typ=top_shifterop) then
- begin
- end;
+ if (op+1<opercnt) and (oper[op+1]^.typ=top_shifterop) then
+ with oper[op+1]^.shifterop^ do
+ begin
+ bytes:=bytes or ((shiftimm and $1F) shl 7);
+ if shiftmode<>SM_RRX then
+ bytes:=bytes or (ord(shiftmode) - ord(SM_LSL)) shl 5
+ else
+ bytes:=bytes or (3 shl 5);
+ if getregtype(rs) <> R_INVALIDREGISTER then
+ begin
+ bytes:=bytes or (1 shl 4);
+ bytes:=bytes or (getsupreg(rs) shl 8);
+ end
+ end;
end;
else
internalerror(2005091103);
end;
end;
- begin
- bytes:=$0;
- i_field:=0;
- { evaluate and set condition code }
-
- { condition code allowed? }
-
- { setup rest of the instruction }
- case insentry^.code[0] of
- #$08:
+ function MakeRegList(reglist: tcpuregisterset): word;
+ var
+ i, w: word;
+ begin
+ result:=0;
+ w:=1;
+ for i:=RS_R0 to RS_R15 do
begin
- { set instruction code }
- bytes:=bytes or (ord(insentry^.code[1]) shl 26);
- bytes:=bytes or (ord(insentry^.code[2]) shl 21);
-
- { set destination }
- bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
-
- { create shifter op }
- setshifterop(1);
-
- { set i field }
- bytes:=bytes or (i_field shl 25);
-
- { set s if necessary }
- if oppostfix=PF_S then
- bytes:=bytes or (1 shl 20);
+ if i in reglist then
+ result:=result or w;
+ w:=w shl 1
end;
- #$ff:
- internalerror(2005091101);
+ end;
+
+ function getcoproc(reg: tregister): byte;
+ begin
+ if reg=NR_p15 then
+ result:=15
else
- internalerror(2005091102);
+ begin
+ Message1(asmw_e_invalid_opcode_and_operands,'Invalid coprocessor port');
+ result:=0;
+ end;
end;
- { we're finished, write code }
- objdata.writebytes(bytes,sizeof(bytes));
- end;
+ function getcoprocreg(reg: tregister): byte;
+ begin
+ result:=getsupreg(reg)-getsupreg(NR_CR0);
+ end;
-{$ifdef dummy}
-(*
-static void gencode (long segment, long offset, int bits,
- insn *ins, char *codes, long insn_end)
-{
- int has_S_code; /* S - setflag */
- int has_B_code; /* B - setflag */
- int has_T_code; /* T - setflag */
- int has_W_code; /* ! => W flag */
- int has_F_code; /* ^ => S flag */
- int keep;
- unsigned char c;
- unsigned char bytes[4];
- long data, size;
- static int cc_code[] = /* bit pattern of cc */
- { /* order as enum in */
- 0x0E, 0x03, 0x02, 0x00, /* nasm.h */
- 0x0A, 0x0C, 0x08, 0x0D,
- 0x09, 0x0B, 0x04, 0x01,
- 0x05, 0x07, 0x06,
- };
-
-
-#ifdef DEBUG
-static char *CC[] =
- { /* condition code names */
- "AL", "CC", "CS", "EQ",
- "GE", "GT", "HI", "LE",
- "LS", "LT", "MI", "NE",
- "PL", "VC", "VS", "",
- "S"
-};
-
-
- has_S_code = (ins->condition & C_SSETFLAG);
- has_B_code = (ins->condition & C_BSETFLAG);
- has_T_code = (ins->condition & C_TSETFLAG);
- has_W_code = (ins->condition & C_EXSETFLAG);
- has_F_code = (ins->condition & C_FSETFLAG);
- ins->condition = (ins->condition & 0x0F);
-
-
- if (rt_debug)
- {
- printf ("gencode: instruction: %s%s", insn_names[ins->opcode],
- CC[ins->condition & 0x0F]);
- if (has_S_code)
- printf ("S");
- if (has_B_code)
- printf ("B");
- if (has_T_code)
- printf ("T");
- if (has_W_code)
- printf ("!");
- if (has_F_code)
- printf ("^");
-
- printf ("\n");
-
- c = *codes;
-
- printf (" (%d) decode - '0x%02X'\n", ins->operands, c);
-
-
- bytes[0] = 0xB;
- bytes[1] = 0xE;
- bytes[2] = 0xE;
- bytes[3] = 0xF;
- }
+ function getmmreg(reg: tregister): byte;
+ begin
+ case reg of
+ NR_D0: result:=0;
+ NR_D1: result:=1;
+ NR_D2: result:=2;
+ NR_D3: result:=3;
+ NR_D4: result:=4;
+ NR_D5: result:=5;
+ NR_D6: result:=6;
+ NR_D7: result:=7;
+ NR_D8: result:=8;
+ NR_D9: result:=9;
+ NR_D10: result:=10;
+ NR_D11: result:=11;
+ NR_D12: result:=12;
+ NR_D13: result:=13;
+ NR_D14: result:=14;
+ NR_D15: result:=15;
+ NR_D16: result:=16;
+ NR_D17: result:=17;
+ NR_D18: result:=18;
+ NR_D19: result:=19;
+ NR_D20: result:=20;
+ NR_D21: result:=21;
+ NR_D22: result:=22;
+ NR_D23: result:=23;
+ NR_D24: result:=24;
+ NR_D25: result:=25;
+ NR_D26: result:=26;
+ NR_D27: result:=27;
+ NR_D28: result:=28;
+ NR_D29: result:=29;
+ NR_D30: result:=30;
+ NR_D31: result:=31;
+
+ NR_S0: result:=0;
+ NR_S1: result:=1;
+ NR_S2: result:=2;
+ NR_S3: result:=3;
+ NR_S4: result:=4;
+ NR_S5: result:=5;
+ NR_S6: result:=6;
+ NR_S7: result:=7;
+ NR_S8: result:=8;
+ NR_S9: result:=9;
+ NR_S10: result:=10;
+ NR_S11: result:=11;
+ NR_S12: result:=12;
+ NR_S13: result:=13;
+ NR_S14: result:=14;
+ NR_S15: result:=15;
+ NR_S16: result:=16;
+ NR_S17: result:=17;
+ NR_S18: result:=18;
+ NR_S19: result:=19;
+ NR_S20: result:=20;
+ NR_S21: result:=21;
+ NR_S22: result:=22;
+ NR_S23: result:=23;
+ NR_S24: result:=24;
+ NR_S25: result:=25;
+ NR_S26: result:=26;
+ NR_S27: result:=27;
+ NR_S28: result:=28;
+ NR_S29: result:=29;
+ NR_S30: result:=30;
+ NR_S31: result:=31;
+ else
+ result:=0;
+ end;
+ end;
- // First condition code in upper nibble
- if (ins->condition < C_NONE)
- {
- c = cc_code[ins->condition] << 4;
- }
- else
- {
- c = cc_code[C_AL] << 4; // is often ALWAYS but not always
- }
+ procedure encodethumbimm(imm: longword);
+ var
+ imm12, tmp: tcgint;
+ shift: integer;
+ found: boolean;
+ begin
+ found:=true;
+ if (imm and $FF) = imm then
+ imm12:=imm
+ else if ((imm shr 16)=(imm and $FFFF)) and
+ ((imm and $FF00FF00) = 0) then
+ imm12:=(imm and $ff) or ($1 shl 8)
+ else if ((imm shr 16)=(imm and $FFFF)) and
+ ((imm and $00FF00FF) = 0) then
+ imm12:=((imm shr 8) and $ff) or ($2 shl 8)
+ else if ((imm shr 16)=(imm and $FFFF)) and
+ (((imm shr 8) and $FF)=(imm and $FF)) then
+ imm12:=(imm and $ff) or ($3 shl 8)
+ else
+ begin
+ found:=false;
+ imm12:=0;
+ for shift:=1 to 31 do
+ begin
+ tmp:=RolDWord(imm,shift);
+ if ((tmp and $FF)=tmp) and
+ ((tmp and $80)=$80) then
+ begin
+ imm12:=(tmp and $7F) or (shift shl 7);
+ found:=true;
+ break;
+ end;
+ end;
+ end;
+ if found then
+ begin
+ bytes:=bytes or (imm12 and $FF);
+ bytes:=bytes or (((imm12 shr 8) and $7) shl 12);
+ bytes:=bytes or (((imm12 shr 11) and $1) shl 26);
+ end
+ else
+ Message1(asmw_e_value_exceeds_bounds, IntToStr(imm));
+ end;
- switch (keep = *codes)
- {
- case 1:
- // B, BL
- ++codes;
- c |= *codes++;
- bytes[0] = c;
+ procedure setthumbshift(op: byte; is_sat: boolean = false);
+ var
+ shift,typ: byte;
+ begin
+ shift:=0;
+ typ:=0;
+ case oper[op]^.shifterop^.shiftmode of
+ SM_LSL: begin typ:=0; shift:=oper[op]^.shifterop^.shiftimm; end;
+ SM_LSR: begin typ:=1; shift:=oper[op]^.shifterop^.shiftimm; if shift=32 then shift:=0; end;
+ SM_ASR: begin typ:=2; shift:=oper[op]^.shifterop^.shiftimm; if shift=32 then shift:=0; end;
+ SM_ROR: begin typ:=3; shift:=oper[op]^.shifterop^.shiftimm; if shift=0 then message(asmw_e_invalid_opcode_and_operands); end;
+ SM_RRX: begin typ:=3; shift:=0; end;
+ end;
- if (ins->oprs[0].segment != segment)
- {
- // fais une relocation
- c = 1;
- data = 0; // Let the linker locate ??
- }
+ if is_sat then
+ begin
+ bytes:=bytes or ((typ and 1) shl 5);
+ bytes:=bytes or ((typ shr 1) shl 21);
+ end
else
- {
- c = 0;
- data = ins->oprs[0].offset - (offset + 8);
-
- if (data % 4)
- {
- errfunc (ERR_NONFATAL, "offset not aligned on 4 bytes");
- }
- }
+ bytes:=bytes or (typ shl 4);
+ bytes:=bytes or (shift and $3) shl 6;
+ bytes:=bytes or ((shift and $1C) shr 2) shl 12;
+ end;
- if (data >= 0x1000)
- {
- errfunc (ERR_NONFATAL, "too long offset");
- }
+ begin
+ bytes:=$0;
+ bytelen:=4;
+ i_field:=0;
+ { evaluate and set condition code }
+ bytes:=bytes or (CondVal[condition] shl 28);
- data = data >> 2;
- bytes[1] = (data >> 16) & 0xFF;
- bytes[2] = (data >> 8) & 0xFF;
- bytes[3] = (data ) & 0xFF;
+ { condition code allowed? }
- if (c == 1)
- {
-// out (offset, segment, &bytes[0], OUT_RAWDATA+1, NO_SEG, NO_SEG);
- out (offset, segment, &bytes[0], OUT_REL3ADR+4, ins->oprs[0].segment, NO_SEG);
- }
- else
- {
- out (offset, segment, &bytes[0], OUT_RAWDATA+4, NO_SEG, NO_SEG);
- }
- return;
-
- case 2:
- // SWI
- ++codes;
- c |= *codes++;
- bytes[0] = c;
- data = ins->oprs[0].offset;
- bytes[1] = (data >> 16) & 0xFF;
- bytes[2] = (data >> 8) & 0xFF;
- bytes[3] = (data) & 0xFF;
- out (offset, segment, &bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
- return;
- case 3:
- // BX
- ++codes;
- c |= *codes++;
- bytes[0] = c;
- bytes[1] = *codes++;
- bytes[2] = *codes++;
- bytes[3] = *codes++;
- c = regval (&ins->oprs[0],1);
- if (c == 15) // PC
- {
- errfunc (ERR_WARNING, "'BX' with R15 has undefined behaviour");
- }
- else if (c > 15)
- {
- errfunc (ERR_NONFATAL, "Illegal register specified for 'BX'");
- }
+ { setup rest of the instruction }
+ case insentry^.code[0] of
+ #$01: // B/BL
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ { set offset }
+ if oper[0]^.typ=top_const then
+ bytes:=bytes or ((oper[0]^.val shr 2) and $ffffff)
+ else
+ begin
+ currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
+ if (currsym.bind<>AB_LOCAL) and (currsym.objsection<>objdata.CurrObjSec) then
+ begin
+ objdata.writereloc(oper[0]^.ref^.offset,0,currsym,RELOC_RELATIVE_24);
+ bytes:=bytes or $fffffe; // TODO: Not sure this is right, but it matches the output of gas
+ end
+ else
+ bytes:=bytes or (((currsym.offset-insoffset-8) shr 2) and $ffffff);
+ end;
+ end;
+ #$02:
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ { set code }
+ bytes:=bytes or (oper[0]^.val and $FFFFFF);
+ end;
+ #$03:
+ begin // BLX/BX
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+
+ bytes:=bytes or getsupreg(oper[0]^.reg);
+ end;
+ #$04..#$07: // SUB
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ { set destination }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+ { set Rn }
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
+ { create shifter op }
+ setshifterop(2);
+ { set I field }
+ bytes:=bytes or (i_field shl 25);
+ { set S if necessary }
+ if oppostfix=PF_S then
+ bytes:=bytes or (1 shl 20);
+ end;
+ #$08,#$0A,#$0B: // MOV
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ { set destination }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+ { create shifter op }
+ setshifterop(1);
+ { set I field }
+ bytes:=bytes or (i_field shl 25);
+ { set S if necessary }
+ if oppostfix=PF_S then
+ bytes:=bytes or (1 shl 20);
+ end;
+ #$0C,#$0E,#$0F: // CMP
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ { set destination }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
+ { create shifter op }
+ setshifterop(1);
+ { set I field }
+ bytes:=bytes or (i_field shl 25);
+ { always set S bit }
+ bytes:=bytes or (1 shl 20);
+ end;
+ #$10: // MRS
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ { set destination }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+
+ case oper[1]^.reg of
+ NR_APSR,NR_CPSR:;
+ NR_SPSR:
+ begin
+ bytes:=bytes or (1 shl 22);
+ end;
+ else
+ Message(asmw_e_invalid_opcode_and_operands);
+ end;
+ end;
+ #$12,#$13: // MSR
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ { set destination }
+
+ if oper[0]^.typ=top_specialreg then
+ begin
+ if (oper[0]^.specialreg<>NR_CPSR) and
+ (oper[0]^.specialreg<>NR_SPSR) then
+ Message1(asmw_e_invalid_opcode_and_operands, '"Invalid special reg"');
+
+ if srC in oper[0]^.specialflags then
+ bytes:=bytes or (1 shl 16);
+ if srX in oper[0]^.specialflags then
+ bytes:=bytes or (1 shl 17);
+ if srS in oper[0]^.specialflags then
+ bytes:=bytes or (1 shl 18);
+ if srF in oper[0]^.specialflags then
+ bytes:=bytes or (1 shl 19);
+
+ { Set R bit }
+ if oper[0]^.specialreg=NR_SPSR then
+ bytes:=bytes or (1 shl 22);
+ end
+ else
+ case oper[0]^.reg of
+ NR_APSR_nzcvq: bytes:=bytes or (2 shl 18);
+ NR_APSR_g: bytes:=bytes or (1 shl 18);
+ NR_APSR_nzcvqg: bytes:=bytes or (3 shl 18);
+ else
+ Message1(asmw_e_invalid_opcode_and_operands, 'Invalid combination APSR bits used');
+ end;
+
+ setshifterop(1);
+ end;
+ #$14: // MUL/MLA r1,r2,r3
+ begin
+ { set instruction code }
+ bytes:=bytes or ord(insentry^.code[1]) shl 24;
+ bytes:=bytes or ord(insentry^.code[2]) shl 16;
+ bytes:=bytes or ord(insentry^.code[3]);
+ { set regs }
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 16;
+ bytes:=bytes or getsupreg(oper[1]^.reg);
+ bytes:=bytes or getsupreg(oper[2]^.reg) shl 8;
+
+ if oppostfix in [PF_S] then
+ bytes:=bytes or (1 shl 20);
+ end;
+ #$15: // MUL/MLA r1,r2,r3,r4
+ begin
+ { set instruction code }
+ bytes:=bytes or ord(insentry^.code[1]) shl 24;
+ bytes:=bytes or ord(insentry^.code[2]) shl 16;
+ bytes:=bytes or ord(insentry^.code[3]) shl 4;
+ { set regs }
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 16;
+ bytes:=bytes or getsupreg(oper[1]^.reg);
+ bytes:=bytes or getsupreg(oper[2]^.reg) shl 8;
+ if ops>3 then
+ bytes:=bytes or getsupreg(oper[3]^.reg) shl 12
+ else
+ bytes:=bytes or ord(insentry^.code[4]) shl 12;
+
+ if oppostfix in [PF_R,PF_X] then
+ bytes:=bytes or (1 shl 5);
+
+ if oppostfix in [PF_S] then
+ bytes:=bytes or (1 shl 20);
+ end;
+ #$16: // MULL r1,r2,r3,r4
+ begin
+ { set instruction code }
+ bytes:=bytes or ord(insentry^.code[1]) shl 24;
+ bytes:=bytes or ord(insentry^.code[2]) shl 16;
+ bytes:=bytes or ord(insentry^.code[3]) shl 4;
+ { set regs }
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+
+ if (ops=3) and (opcode=A_PKHTB) then
+ begin
+ bytes:=bytes or getsupreg(oper[1]^.reg);
+ bytes:=bytes or getsupreg(oper[2]^.reg) shl 16;
+ end
+ else
+ begin
+ bytes:=bytes or getsupreg(oper[1]^.reg) shl 16;
+ bytes:=bytes or getsupreg(oper[2]^.reg);
+ end;
+
+ if ops=4 then
+ begin
+ if oper[3]^.typ=top_shifterop then
+ begin
+ if opcode in [A_PKHBT,A_PKHTB] then
+ begin
+ if ((opcode=A_PKHTB) and
+ (oper[3]^.shifterop^.shiftmode <> SM_ASR)) or
+ ((opcode=A_PKHBT) and
+ (oper[3]^.shifterop^.shiftmode <> SM_LSL)) or
+ (oper[3]^.shifterop^.rs<>NR_NO) then
+ Message1(asmw_e_invalid_opcode_and_operands,GetString);
+
+ bytes:=bytes or ((oper[3]^.shifterop^.shiftimm and $1F) shl 7);
+ end
+ else
+ begin
+ if (oper[3]^.shifterop^.shiftmode<>sm_ror) or
+ (oper[3]^.shifterop^.rs<>NR_NO) or
+ (not (oper[3]^.shifterop^.shiftimm in [0,8,16,24])) then
+ Message1(asmw_e_invalid_opcode_and_operands,GetString);
+
+ bytes:=bytes or (((oper[3]^.shifterop^.shiftimm shr 3) and $3) shl 10);
+ end;
+ end
+ else
+ bytes:=bytes or getsupreg(oper[3]^.reg) shl 8;
+ end;
+
+ if PF_S=oppostfix then
+ bytes:=bytes or (1 shl 20);
+ if PF_X=oppostfix then
+ bytes:=bytes or (1 shl 5);
+ end;
+ #$17: // LDR/STR
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ { set Rn and Rd }
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+ bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+ if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
+ begin
+ { set offset }
+ offset:=0;
+ currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
+ if assigned(currsym) then
+ offset:=currsym.offset-insoffset-8;
+ offset:=offset+oper[1]^.ref^.offset;
+ if offset>=0 then
+ { set U flag }
+ bytes:=bytes or (1 shl 23)
+ else
+ offset:=-offset;
+ bytes:=bytes or (offset and $FFF);
+ end
+ else
+ begin
+ { set U flag }
+ if oper[1]^.ref^.signindex>=0 then
+ bytes:=bytes or (1 shl 23);
+ { set I flag }
+ bytes:=bytes or (1 shl 25);
+ bytes:=bytes or getsupreg(oper[1]^.ref^.index);
+ { set shift }
+ with oper[1]^.ref^ do
+ if shiftmode<>SM_None then
+ begin
+ bytes:=bytes or ((shiftimm and $1F) shl 7);
+ if shiftmode<>SM_RRX then
+ bytes:=bytes or (ord(shiftmode) - ord(SM_LSL)) shl 5
+ else
+ bytes:=bytes or (3 shl 5);
+ end
+ end;
+ { set W bit }
+ if oper[1]^.ref^.addressmode=AM_PREINDEXED then
+ bytes:=bytes or (1 shl 21);
+ { set P bit if necessary }
+ if oper[1]^.ref^.addressmode<>AM_POSTINDEXED then
+ bytes:=bytes or (1 shl 24);
+ end;
+ #$18: // LDREX/STREX
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+ { set Rn and Rd }
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+ if (ops=3) then
+ begin
+ if opcode<>A_LDREXD then
+ bytes:=bytes or getsupreg(oper[1]^.reg);
+
+ bytes:=bytes or (getsupreg(oper[2]^.ref^.base) shl 16);
+ end
+ else if (ops=4) then // STREXD
+ begin
+ if opcode<>A_LDREXD then
+ bytes:=bytes or getsupreg(oper[1]^.reg);
+
+ bytes:=bytes or (getsupreg(oper[3]^.ref^.base) shl 16);
+ end
+ else
+ bytes:=bytes or (getsupreg(oper[1]^.ref^.base) shl 16);
+ end;
+ #$19: // LDRD/STRD
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+ { set Rn and Rd }
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+
+ refoper:=oper[1];
+ if ops=3 then
+ refoper:=oper[2];
+
+ bytes:=bytes or getsupreg(refoper^.ref^.base) shl 16;
+ if getregtype(refoper^.ref^.index)=R_INVALIDREGISTER then
+ begin
+ bytes:=bytes or (1 shl 22);
+ { set offset }
+ offset:=0;
+ currsym:=objdata.symbolref(refoper^.ref^.symbol);
+ if assigned(currsym) then
+ offset:=currsym.offset-insoffset-8;
+ offset:=offset+refoper^.ref^.offset;
+ if offset>=0 then
+ { set U flag }
+ bytes:=bytes or (1 shl 23)
+ else
+ offset:=-offset;
+ bytes:=bytes or (offset and $F);
+ bytes:=bytes or ((offset and $F0) shl 4);
+ end
+ else
+ begin
+ { set U flag }
+ if refoper^.ref^.signindex>=0 then
+ bytes:=bytes or (1 shl 23);
+ bytes:=bytes or getsupreg(refoper^.ref^.index);
+ end;
+ { set W bit }
+ if refoper^.ref^.addressmode=AM_PREINDEXED then
+ bytes:=bytes or (1 shl 21);
+ { set P bit if necessary }
+ if refoper^.ref^.addressmode<>AM_POSTINDEXED then
+ bytes:=bytes or (1 shl 24);
+ end;
+ #$1A: // QADD/QSUB
+ begin
+ { set instruction code }
+ bytes:=bytes or ord(insentry^.code[1]) shl 24;
+ bytes:=bytes or ord(insentry^.code[2]) shl 16;
+ bytes:=bytes or ord(insentry^.code[3]) shl 4;
+ { set regs }
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+ bytes:=bytes or getsupreg(oper[1]^.reg) shl 0;
+ bytes:=bytes or getsupreg(oper[2]^.reg) shl 16;
+ end;
+ #$1B:
+ begin
+ { set instruction code }
+ bytes:=bytes or ord(insentry^.code[1]) shl 24;
+ bytes:=bytes or ord(insentry^.code[2]) shl 16;
+ bytes:=bytes or ord(insentry^.code[3]) shl 4;
+ { set regs }
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+ bytes:=bytes or getsupreg(oper[1]^.reg);
+ if ops=3 then
+ begin
+ if (oper[2]^.shifterop^.shiftmode<>sm_ror) or
+ (oper[2]^.shifterop^.rs<>NR_NO) or
+ (not (oper[2]^.shifterop^.shiftimm in [0,8,16,24])) then
+ Message1(asmw_e_invalid_opcode_and_operands,GetString);
+
+ bytes:=bytes or (((oper[2]^.shifterop^.shiftimm shr 3) and $3) shl 10);
+ end;
+ end;
+ #$1C: // MCR/MRC
+ begin
+ { set instruction code }
+ bytes:=bytes or ord(insentry^.code[1]) shl 24;
+ bytes:=bytes or ord(insentry^.code[2]) shl 16;
+ bytes:=bytes or ord(insentry^.code[3]) shl 4;
+ { set regs and operands }
+ bytes:=bytes or getcoproc(oper[0]^.reg) shl 8;
+ bytes:=bytes or ((oper[1]^.val and $7) shl 21);
+ bytes:=bytes or getsupreg(oper[2]^.reg) shl 12;
+ bytes:=bytes or getcoprocreg(oper[3]^.reg) shl 16;
+ bytes:=bytes or getcoprocreg(oper[4]^.reg);
+ if ops > 5 then
+ bytes:=bytes or ((oper[5]^.val and $7) shl 5);
+ end;
+ #$1D: // MCRR/MRRC
+ begin
+ { set instruction code }
+ bytes:=bytes or ord(insentry^.code[1]) shl 24;
+ bytes:=bytes or ord(insentry^.code[2]) shl 16;
+ bytes:=bytes or ord(insentry^.code[3]) shl 4;
+ { set regs and operands }
+ bytes:=bytes or getcoproc(oper[0]^.reg) shl 8;
+ bytes:=bytes or ((oper[1]^.val and $7) shl 4);
+ bytes:=bytes or getsupreg(oper[2]^.reg) shl 12;
+ bytes:=bytes or getsupreg(oper[3]^.reg) shl 16;
+ bytes:=bytes or getcoprocreg(oper[4]^.reg);
+ end;
+ #$1E: // LDRHT/STRHT
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+ { set Rn and Rd }
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+
+ refoper:=oper[1];
+
+ bytes:=bytes or getsupreg(refoper^.ref^.base) shl 16;
+ if getregtype(refoper^.ref^.index)=R_INVALIDREGISTER then
+ begin
+ bytes:=bytes or (1 shl 22);
+ { set offset }
+ offset:=0;
+ currsym:=objdata.symbolref(refoper^.ref^.symbol);
+ if assigned(currsym) then
+ offset:=currsym.offset-insoffset-8;
+ offset:=offset+refoper^.ref^.offset;
+
+ if offset>=0 then
+ { set U flag }
+ bytes:=bytes or (1 shl 23)
+ else
+ offset:=-offset;
+ bytes:=bytes or (offset and $F);
+ bytes:=bytes or ((offset and $F0) shl 4);
+ end
+ else
+ begin
+ { set U flag }
+ if refoper^.ref^.signindex>=0 then
+ bytes:=bytes or (1 shl 23);
+ bytes:=bytes or getsupreg(refoper^.ref^.index);
+ end;
+ end;
+ #$22: // LDRH/STRH
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 16);
+ bytes:=bytes or ord(insentry^.code[2]);
+ { src/dest register (Rd) }
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+ { base register (Rn) }
+ bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+ if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
+ begin
+ bytes:=bytes or (1 shl 22); // with immediate offset
+ offset:=oper[1]^.ref^.offset;
+ if offset>=0 then
+ { set U flag }
+ bytes:=bytes or (1 shl 23)
+ else
+ offset:=-offset;
+ bytes:=bytes or (offset and $F);
+ bytes:=bytes or ((offset and $F0) shl 4);
+ end
+ else
+ begin
+ { set U flag }
+ if oper[1]^.ref^.signindex>=0 then
+ bytes:=bytes or (1 shl 23);
+ bytes:=bytes or getsupreg(oper[1]^.ref^.index);
+ end;
+ { set W bit }
+ if oper[1]^.ref^.addressmode=AM_PREINDEXED then
+ bytes:=bytes or (1 shl 21);
+ { set P bit if necessary }
+ if oper[1]^.ref^.addressmode<>AM_POSTINDEXED then
+ bytes:=bytes or (1 shl 24);
+ end;
+ #$25: // PLD/PLI
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+ { set Rn and Rd }
+ bytes:=bytes or getsupreg(oper[0]^.ref^.base) shl 16;
+ if getregtype(oper[0]^.ref^.index)=R_INVALIDREGISTER then
+ begin
+ { set offset }
+ offset:=0;
+ currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
+ if assigned(currsym) then
+ offset:=currsym.offset-insoffset-8;
+ offset:=offset+oper[0]^.ref^.offset;
+ if offset>=0 then
+ begin
+ { set U flag }
+ bytes:=bytes or (1 shl 23);
+ bytes:=bytes or offset
+ end
+ else
+ begin
+ offset:=-offset;
+ bytes:=bytes or offset
+ end;
+ end
+ else
+ begin
+ bytes:=bytes or (1 shl 25);
+ { set U flag }
+ if oper[0]^.ref^.signindex>=0 then
+ bytes:=bytes or (1 shl 23);
+ bytes:=bytes or getsupreg(oper[0]^.ref^.index);
+ { set shift }
+ with oper[0]^.ref^ do
+ if shiftmode<>SM_None then
+ begin
+ bytes:=bytes or ((shiftimm and $1F) shl 7);
+ if shiftmode<>SM_RRX then
+ bytes:=bytes or (ord(shiftmode) - ord(SM_LSL)) shl 5
+ else
+ bytes:=bytes or (3 shl 5);
+ end
+ end;
+ end;
+ #$26: // LDM/STM
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 20);
+
+ if ops>1 then
+ begin
+ if oper[0]^.typ=top_ref then
+ begin
+ { set W bit }
+ if oper[0]^.ref^.addressmode=AM_PREINDEXED then
+ bytes:=bytes or (1 shl 21);
+ { set Rn }
+ bytes:=bytes or (getsupreg(oper[0]^.ref^.index) shl 16);
+ end
+ else { typ=top_reg }
+ begin
+ { set Rn }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
+ end;
+
+ if oper[1]^.usermode then
+ begin
+ if (oper[0]^.typ=top_ref) then
+ begin
+ if (opcode=A_LDM) and
+ (RS_PC in oper[1]^.regset^) then
+ begin
+ // Valid exception return
+ end
+ else
+ Message(asmw_e_invalid_opcode_and_operands);
+ end;
+
+ bytes:=bytes or (1 shl 22);
+ end;
+ { reglist }
+ bytes:=bytes or MakeRegList(oper[1]^.regset^);
+ end
+ else
+ begin
+ { push/pop }
+ { Set W and Rn to SP }
+ if opcode=A_PUSH then
+ bytes:=bytes or (1 shl 21);
+ bytes:=bytes or ($D shl 16);
+ { reglist }
+ bytes:=bytes or MakeRegList(oper[0]^.regset^);
+ end;
+ { set P bit }
+ if (opcode=A_LDM) and (oppostfix in [PF_ED,PF_EA,PF_IB,PF_DB])
+ or (opcode=A_STM) and (oppostfix in [PF_FA,PF_FD,PF_IB,PF_DB])
+ or (opcode=A_PUSH) then
+ bytes:=bytes or (1 shl 24);
+ { set U bit }
+ if (opcode=A_LDM) and (oppostfix in [PF_None,PF_ED,PF_FD,PF_IB,PF_IA])
+ or (opcode=A_STM) and (oppostfix in [PF_None,PF_FA,PF_EA,PF_IB,PF_IA])
+ or (opcode=A_POP) then
+ bytes:=bytes or (1 shl 23);
+ end;
+ #$27: // SWP/SWPB
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 20);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 4);
+ { set regs }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+ bytes:=bytes or getsupreg(oper[1]^.reg);
+ if ops=3 then
+ bytes:=bytes or (getsupreg(oper[2]^.ref^.base) shl 16);
+ end;
+ #$28: // BX/BLX
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ { set offset }
+ if oper[0]^.typ=top_const then
+ bytes:=bytes or ((oper[0]^.val shr 2) and $ffffff)
+ else
+ begin
+ currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
+ if (currsym.bind<>AB_LOCAL) and (currsym.objsection<>objdata.CurrObjSec) then
+ begin
+ bytes:=bytes or $fffffe; // TODO: Not sure this is right, but it matches the output of gas
+ objdata.writereloc(oper[0]^.ref^.offset,0,currsym,RELOC_RELATIVE_24_THUMB);
+ end
+ else
+ begin
+ offset:=((currsym.offset-insoffset-8) and $3fffffe);
+
+ { Turn BLX into BL if the destination isn't odd, could happen with recursion }
+ if not odd(offset shr 1) then
+ bytes:=(bytes and $EB000000) or $EB000000;
+
+ bytes:=bytes or ((offset shr 2) and $ffffff);
+ bytes:=bytes or ((offset shr 1) and $1) shl 24;
+ end;
+ end;
+ end;
+ #$29: // SUB
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ { set regs }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+ { set S if necessary }
+ if oppostfix=PF_S then
+ bytes:=bytes or (1 shl 20);
+ end;
+ #$2A:
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+ { set opers }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+ if opcode in [A_SSAT, A_SSAT16] then
+ bytes:=bytes or (((oper[1]^.val-1) and $1F) shl 16)
+ else
+ bytes:=bytes or ((oper[1]^.val and $1F) shl 16);
+ bytes:=bytes or getsupreg(oper[2]^.reg);
+
+ if (ops>3) and
+ (oper[3]^.typ=top_shifterop) and
+ (oper[3]^.shifterop^.rs=NR_NO) then
+ begin
+ bytes:=bytes or ((oper[3]^.shifterop^.shiftimm and $1F) shl 7);
+ if oper[3]^.shifterop^.shiftmode=SM_ASR then
+ bytes:=bytes or (1 shl 6)
+ else if oper[3]^.shifterop^.shiftmode<>SM_LSL then
+ Message1(asmw_e_invalid_opcode_and_operands,GetString);
+ end;
+ end;
+ #$2B: // SETEND
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+ { set endian specifier }
+ bytes:=bytes or ((oper[0]^.val and 1) shl 9);
+ end;
+ #$2C: // MOVW
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ { set destination }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+ { set imm }
+ bytes:=bytes or (oper[1]^.val and $FFF);
+ bytes:=bytes or ((oper[1]^.val and $F000) shl 4);
+ end;
+ #$2D: // BFX
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+
+ if ops=3 then
+ begin
+ msb:=(oper[1]^.val+oper[2]^.val-1);
+
+ { set destination }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+ { set immediates }
+ bytes:=bytes or ((oper[1]^.val and $1F) shl 7);
+ bytes:=bytes or ((msb and $1F) shl 16);
+ end
+ else
+ begin
+ if opcode in [A_BFC,A_BFI] then
+ msb:=(oper[2]^.val+oper[3]^.val-1)
+ else
+ msb:=oper[3]^.val-1;
+
+ { set destination }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+ bytes:=bytes or getsupreg(oper[1]^.reg);
+ { set immediates }
+ bytes:=bytes or ((oper[2]^.val and $1F) shl 7);
+ bytes:=bytes or ((msb and $1F) shl 16);
+ end;
+ end;
+ #$2E: // Cache stuff
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+ { set code }
+ bytes:=bytes or (oper[0]^.val and $F);
+ end;
+ #$2F: // Nop
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+ end;
+ #$30: // Shifts
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+ { set destination }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+ bytes:=bytes or getsupreg(oper[1]^.reg);
+ if ops>2 then
+ begin
+ { set shift }
+ if oper[2]^.typ=top_reg then
+ bytes:=bytes or (getsupreg(oper[2]^.reg) shl 8)
+ else
+ bytes:=bytes or ((oper[2]^.val and $1F) shl 7);
+ end;
+ { set S if necessary }
+ if oppostfix=PF_S then
+ bytes:=bytes or (1 shl 20);
+ end;
+ #$31: // BKPT
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 0);
+ { set imm }
+ bytes:=bytes or (oper[0]^.val and $FFF0) shl 4;
+ bytes:=bytes or (oper[0]^.val and $F);
+ end;
+ #$32: // CLZ/REV
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+ { set regs }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+ bytes:=bytes or getsupreg(oper[1]^.reg);
+ end;
+ #$33:
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ { set regs }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+
+ if oper[1]^.typ=top_ref then
+ begin
+ { set offset }
+ offset:=0;
+ currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
+ if assigned(currsym) then
+ offset:=currsym.offset-insoffset-8;
+ offset:=offset+oper[1]^.ref^.offset;
+ if offset>=0 then
+ begin
+ { set U flag }
+ bytes:=bytes or (1 shl 23);
+ bytes:=bytes or offset
+ end
+ else
+ begin
+ bytes:=bytes or (1 shl 22);
+ offset:=-offset;
+ bytes:=bytes or offset
+ end;
+ end
+ else
+ begin
+ if is_shifter_const(oper[1]^.val,r) then
+ begin
+ setshifterop(1);
+ bytes:=bytes or (1 shl 23);
+ end
+ else
+ begin
+ bytes:=bytes or (1 shl 22);
+ oper[1]^.val:=-oper[1]^.val;
+ setshifterop(1);
+ end;
+ end;
+ end;
+ #$40,#$90: // VMOV
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+
+ { set regs }
+ Rd:=0;
+ Rn:=0;
+ Rm:=0;
+
+ case oppostfix of
+ PF_None:
+ begin
+ if ops=4 then
+ begin
+ if (getregtype(oper[0]^.reg)=R_MMREGISTER) and
+ (getregtype(oper[2]^.reg)=R_INTREGISTER) then
+ begin
+ Rd:=getmmreg(oper[0]^.reg);
+ Rm:=getsupreg(oper[2]^.reg);
+ Rn:=getsupreg(oper[3]^.reg);
+ end
+ else if (getregtype(oper[0]^.reg)=R_INTREGISTER) and
+ (getregtype(oper[2]^.reg)=R_MMREGISTER) then
+ begin
+ Rm:=getsupreg(oper[0]^.reg);
+ Rn:=getsupreg(oper[1]^.reg);
+ Rd:=getmmreg(oper[2]^.reg);
+ end
+ else
+ message(asmw_e_invalid_opcode_and_operands);
+
+ bytes:=bytes or (((Rd and $1E) shr 1) shl 0);
+ bytes:=bytes or ((Rd and $1) shl 5);
+
+ bytes:=bytes or (Rm shl 12);
+ bytes:=bytes or (Rn shl 16);
+ end
+ else if ops=3 then
+ begin
+ if (getregtype(oper[0]^.reg)=R_MMREGISTER) and
+ (getregtype(oper[1]^.reg)=R_INTREGISTER) then
+ begin
+ Rd:=getmmreg(oper[0]^.reg);
+ Rm:=getsupreg(oper[1]^.reg);
+ Rn:=getsupreg(oper[2]^.reg);
+ end
+ else if (getregtype(oper[0]^.reg)=R_INTREGISTER) and
+ (getregtype(oper[2]^.reg)=R_MMREGISTER) then
+ begin
+ Rm:=getsupreg(oper[0]^.reg);
+ Rn:=getsupreg(oper[1]^.reg);
+ Rd:=getmmreg(oper[2]^.reg);
+ end
+ else
+ message(asmw_e_invalid_opcode_and_operands);
+
+ bytes:=bytes or ((Rd and $F) shl 0);
+ bytes:=bytes or ((Rd and $10) shl 1);
+
+ bytes:=bytes or (Rm shl 12);
+ bytes:=bytes or (Rn shl 16);
+ end
+ else if ops=2 then
+ begin
+ if (getregtype(oper[0]^.reg)=R_MMREGISTER) and
+ (getregtype(oper[1]^.reg)=R_INTREGISTER) then
+ begin
+ Rd:=getmmreg(oper[0]^.reg);
+ Rm:=getsupreg(oper[1]^.reg);
+ end
+ else if (getregtype(oper[0]^.reg)=R_INTREGISTER) and
+ (getregtype(oper[1]^.reg)=R_MMREGISTER) then
+ begin
+ Rm:=getsupreg(oper[0]^.reg);
+ Rd:=getmmreg(oper[1]^.reg);
+ end
+ else
+ message(asmw_e_invalid_opcode_and_operands);
+
+ bytes:=bytes or (((Rd and $1E) shr 1) shl 16);
+ bytes:=bytes or ((Rd and $1) shl 7);
+
+ bytes:=bytes or (Rm shl 12);
+ end;
+ end;
+ PF_F32:
+ begin
+ if (getregtype(oper[0]^.reg)<>R_MMREGISTER) or
+ (getregtype(oper[1]^.reg)<>R_MMREGISTER) then
+ Message(asmw_e_invalid_opcode_and_operands);
+
+ Rd:=getmmreg(oper[0]^.reg);
+ Rm:=getmmreg(oper[1]^.reg);
+
+ bytes:=bytes or (((Rd and $1E) shr 1) shl 12);
+ bytes:=bytes or ((Rd and $1) shl 22);
+
+ bytes:=bytes or (((Rm and $1E) shr 1) shl 0);
+ bytes:=bytes or ((Rm and $1) shl 5);
+ end;
+ PF_F64:
+ begin
+ if (getregtype(oper[0]^.reg)<>R_MMREGISTER) or
+ (getregtype(oper[1]^.reg)<>R_MMREGISTER) then
+ Message(asmw_e_invalid_opcode_and_operands);
- bytes[3] |= (c & 0x0F);
- out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
- return;
-
- case 4: // AND Rd,Rn,Rm
- case 5: // AND Rd,Rn,Rm,<shift>Rs
- case 6: // AND Rd,Rn,Rm,<shift>imm
- case 7: // AND Rd,Rn,<shift>imm
- ++codes;
-#ifdef DEBUG
- if (rt_debug)
- {
- printf (" decode - '0x%02X'\n", keep);
- printf (" code - '0x%02X'\n", (unsigned char) ( *codes));
- }
-#endif
- bytes[0] = c | *codes;
- ++codes;
-
- bytes[1] = *codes;
- if (has_S_code)
- bytes[1] |= 0x10;
- c = regval (&ins->oprs[1],1);
- // Rn in low nibble
- bytes[1] |= c;
-
- // Rd in high nibble
- bytes[2] = regval (&ins->oprs[0],1) << 4;
-
- if (keep != 7)
- {
- // Rm in low nibble
- bytes[3] = regval (&ins->oprs[2],1);
- }
+ Rd:=getmmreg(oper[0]^.reg);
+ Rm:=getmmreg(oper[1]^.reg);
- // Shifts if any
- if (keep == 5 || keep == 6)
- {
- // Shift in bytes 2 and 3
- if (keep == 5)
- {
- // Rs
- c = regval (&ins->oprs[3],1);
- bytes[2] |= c;
-
- c = 0x10; // Set bit 4 in byte[3]
- }
- if (keep == 6)
- {
- c = (ins->oprs[3].offset) & 0x1F;
-
- // #imm
- bytes[2] |= c >> 1;
- if (c & 0x01)
- {
- bytes[3] |= 0x80;
- }
- c = 0; // Clr bit 4 in byte[3]
- }
- // <shift>
- c |= shiftval (&ins->oprs[3]) << 5;
-
- bytes[3] |= c;
- }
+ bytes:=bytes or (1 shl 8);
- // reg,reg,imm
- if (keep == 7)
- {
- int shimm;
+ bytes:=bytes or ((Rd and $F) shl 12);
+ bytes:=bytes or (((Rd and $10) shr 4) shl 22);
- shimm = imm_shift (ins->oprs[2].offset);
+ bytes:=bytes or (Rm and $F);
+ bytes:=bytes or ((Rm and $10) shl 1);
+ end;
+ end;
+ end;
+ #$41,#$91: // VMRS/VMSR
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+ { set regs }
+ if (opcode=A_VMRS) or
+ (opcode=A_FMRX) then
+ begin
+ case oper[1]^.reg of
+ NR_FPSID: Rn:=$0;
+ NR_FPSCR: Rn:=$1;
+ NR_MVFR1: Rn:=$6;
+ NR_MVFR0: Rn:=$7;
+ NR_FPEXC: Rn:=$8;
+ else
+ Rn:=0;
+ message(asmw_e_invalid_opcode_and_operands);
+ end;
- if (shimm == -1)
- {
- errfunc (ERR_NONFATAL, "cannot create that constant");
- }
- bytes[3] = shimm & 0xFF;
- bytes[2] |= (shimm & 0xF00) >> 8;
- }
+ bytes:=bytes or (Rn shl 16);
- out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
- return;
-
- case 8: // MOV Rd,Rm
- case 9: // MOV Rd,Rm,<shift>Rs
- case 0xA: // MOV Rd,Rm,<shift>imm
- case 0xB: // MOV Rd,<shift>imm
- ++codes;
-#ifdef DEBUG
- if (rt_debug)
- {
- printf (" decode - '0x%02X'\n", keep);
- printf (" code - '0x%02X'\n", (unsigned char) ( *codes));
- }
-#endif
- bytes[0] = c | *codes;
- ++codes;
+ if oper[0]^.reg=NR_APSR_nzcv then
+ bytes:=bytes or ($F shl 12)
+ else
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+ end
+ else
+ begin
+ case oper[0]^.reg of
+ NR_FPSID: Rn:=$0;
+ NR_FPSCR: Rn:=$1;
+ NR_FPEXC: Rn:=$8;
+ else
+ Rn:=0;
+ message(asmw_e_invalid_opcode_and_operands);
+ end;
- bytes[1] = *codes;
- if (has_S_code)
- bytes[1] |= 0x10;
+ bytes:=bytes or (Rn shl 16);
- // Rd in high nibble
- bytes[2] = regval (&ins->oprs[0],1) << 4;
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 12);
+ end;
+ end;
+ #$42,#$92: // VMUL
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+ { set regs }
+ if ops=3 then
+ begin
+ Rd:=getmmreg(oper[0]^.reg);
+ Rn:=getmmreg(oper[1]^.reg);
+ Rm:=getmmreg(oper[2]^.reg);
+ end
+ else if ops=1 then
+ begin
+ Rd:=getmmreg(oper[0]^.reg);
+ Rn:=0;
+ Rm:=0;
+ end
+ else if oper[1]^.typ=top_const then
+ begin
+ Rd:=getmmreg(oper[0]^.reg);
+ Rn:=0;
+ Rm:=0;
+ end
+ else
+ begin
+ Rd:=getmmreg(oper[0]^.reg);
+ Rn:=0;
+ Rm:=getmmreg(oper[1]^.reg);
+ end;
- if (keep != 0x0B)
- {
- // Rm in low nibble
- bytes[3] = regval (&ins->oprs[1],1);
- }
+ if (oppostfix=PF_F32) or (insentry^.code[5]=#1) then
+ begin
+ D:=rd and $1; Rd:=Rd shr 1;
+ N:=rn and $1; Rn:=Rn shr 1;
+ M:=rm and $1; Rm:=Rm shr 1;
+ end
+ else
+ begin
+ D:=(rd shr 4) and $1; Rd:=Rd and $F;
+ N:=(rn shr 4) and $1; Rn:=Rn and $F;
+ M:=(rm shr 4) and $1; Rm:=Rm and $F;
- // Shifts if any
- if (keep == 0x09 || keep == 0x0A)
- {
- // Shift in bytes 2 and 3
- if (keep == 0x09)
- {
- // Rs
- c = regval (&ins->oprs[2],1);
- bytes[2] |= c;
-
- c = 0x10; // Set bit 4 in byte[3]
- }
- if (keep == 0x0A)
- {
- c = (ins->oprs[2].offset) & 0x1F;
-
- // #imm
- bytes[2] |= c >> 1;
- if (c & 0x01)
- {
- bytes[3] |= 0x80;
- }
- c = 0; // Clr bit 4 in byte[3]
- }
- // <shift>
- c |= shiftval (&ins->oprs[2]) << 5;
-
- bytes[3] |= c;
- }
+ bytes:=bytes or (1 shl 8);
+ end;
- // reg,imm
- if (keep == 0x0B)
- {
- int shimm;
+ bytes:=bytes or (Rd shl 12);
+ bytes:=bytes or (Rn shl 16);
+ bytes:=bytes or (Rm shl 0);
- shimm = imm_shift (ins->oprs[1].offset);
+ bytes:=bytes or (D shl 22);
+ bytes:=bytes or (N shl 7);
+ bytes:=bytes or (M shl 5);
+ end;
+ #$43,#$93: // VCVT
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+ { set regs }
+ Rd:=getmmreg(oper[0]^.reg);
+ Rm:=getmmreg(oper[1]^.reg);
+
+ if (ops=2) and
+ (oppostfix in [PF_F32F64,PF_F64F32]) then
+ begin
+ if oppostfix=PF_F32F64 then
+ begin
+ bytes:=bytes or (1 shl 8);
- if (shimm == -1)
- {
- errfunc (ERR_NONFATAL, "cannot create that constant");
- }
- bytes[3] = shimm & 0xFF;
- bytes[2] |= (shimm & 0xF00) >> 8;
- }
+ D:=rd and $1; Rd:=Rd shr 1;
+ M:=(rm shr 4) and $1; Rm:=Rm and $F;
+ end
+ else
+ begin
+ D:=(rd shr 4) and $1; Rd:=Rd and $F;
+ M:=rm and $1; Rm:=Rm shr 1;
+ end;
- out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
- return;
+ bytes:=bytes and $FFF0FFFF;
+ bytes:=bytes or ($7 shl 16);
+ bytes:=bytes or (Rd shl 12);
+ bytes:=bytes or (Rm shl 0);
- case 0xC: // CMP Rn,Rm
- case 0xD: // CMP Rn,Rm,<shift>Rs
- case 0xE: // CMP Rn,Rm,<shift>imm
- case 0xF: // CMP Rn,<shift>imm
- ++codes;
+ bytes:=bytes or (D shl 22);
+ bytes:=bytes or (M shl 5);
+ end
+ else if (ops=2) and
+ (oppostfix=PF_None) then
+ begin
+ d:=0;
+ case getsubreg(oper[0]^.reg) of
+ R_SUBNONE:
+ rd:=getsupreg(oper[0]^.reg);
+ R_SUBFS:
+ begin
+ rd:=getmmreg(oper[0]^.reg);
- bytes[0] = c | *codes++;
+ d:=rd and 1;
+ rd:=rd shr 1;
+ end;
+ R_SUBFD:
+ begin
+ rd:=getmmreg(oper[0]^.reg);
- bytes[1] = *codes;
+ d:=(rd shr 4) and 1;
+ rd:=rd and $F;
+ end;
+ end;
- // Implicit S code
- bytes[1] |= 0x10;
+ m:=0;
+ case getsubreg(oper[1]^.reg) of
+ R_SUBNONE:
+ rm:=getsupreg(oper[1]^.reg);
+ R_SUBFS:
+ begin
+ rm:=getmmreg(oper[1]^.reg);
- c = regval (&ins->oprs[0],1);
- // Rn in low nibble
- bytes[1] |= c;
+ m:=rm and 1;
+ rm:=rm shr 1;
+ end;
+ R_SUBFD:
+ begin
+ rm:=getmmreg(oper[1]^.reg);
- // No destination
- bytes[2] = 0;
+ m:=(rm shr 4) and 1;
+ rm:=rm and $F;
+ end;
+ end;
- if (keep != 0x0B)
- {
- // Rm in low nibble
- bytes[3] = regval (&ins->oprs[1],1);
- }
+ bytes:=bytes or (Rd shl 12);
+ bytes:=bytes or (Rm shl 0);
- // Shifts if any
- if (keep == 0x0D || keep == 0x0E)
- {
- // Shift in bytes 2 and 3
- if (keep == 0x0D)
- {
- // Rs
- c = regval (&ins->oprs[2],1);
- bytes[2] |= c;
-
- c = 0x10; // Set bit 4 in byte[3]
- }
- if (keep == 0x0E)
- {
- c = (ins->oprs[2].offset) & 0x1F;
-
- // #imm
- bytes[2] |= c >> 1;
- if (c & 0x01)
- {
- bytes[3] |= 0x80;
- }
- c = 0; // Clr bit 4 in byte[3]
- }
- // <shift>
- c |= shiftval (&ins->oprs[2]) << 5;
-
- bytes[3] |= c;
- }
+ bytes:=bytes or (D shl 22);
+ bytes:=bytes or (M shl 5);
+ end
+ else if ops=2 then
+ begin
+ case oppostfix of
+ PF_S32F64,
+ PF_U32F64,
+ PF_F64S32,
+ PF_F64U32:
+ bytes:=bytes or (1 shl 8);
+ end;
- // reg,imm
- if (keep == 0x0F)
- {
- int shimm;
+ if oppostfix in [PF_S32F32,PF_S32F64,PF_U32F32,PF_U32F64] then
+ begin
+ case oppostfix of
+ PF_S32F64,
+ PF_S32F32:
+ bytes:=bytes or (1 shl 16);
+ end;
- shimm = imm_shift (ins->oprs[1].offset);
+ bytes:=bytes or (1 shl 18);
- if (shimm == -1)
- {
- errfunc (ERR_NONFATAL, "cannot create that constant");
- }
- bytes[3] = shimm & 0xFF;
- bytes[2] |= (shimm & 0xF00) >> 8;
- }
+ D:=rd and $1; Rd:=Rd shr 1;
- out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
- return;
+ if oppostfix in [PF_S32F64,PF_U32F64] then
+ begin
+ M:=(rm shr 4) and $1; Rm:=Rm and $F;
+ end
+ else
+ begin
+ M:=rm and $1; Rm:=Rm shr 1;
+ end;
+ end
+ else
+ begin
+ case oppostfix of
+ PF_F64S32,
+ PF_F32S32:
+ bytes:=bytes or (1 shl 7);
+ else
+ bytes:=bytes and $FFFFFF7F;
+ end;
- case 0x10: // MRS Rd,<psr>
- ++codes;
+ M:=rm and $1; Rm:=Rm shr 1;
- bytes[0] = c | *codes++;
+ if oppostfix in [PF_F64S32,PF_F64U32] then
+ begin
+ D:=(rd shr 4) and $1; Rd:=Rd and $F;
+ end
+ else
+ begin
+ D:=rd and $1; Rd:=Rd shr 1;
+ end
+ end;
- bytes[1] = *codes++;
+ bytes:=bytes or (Rd shl 12);
+ bytes:=bytes or (Rm shl 0);
- // Rd
- c = regval (&ins->oprs[0],1);
+ bytes:=bytes or (D shl 22);
+ bytes:=bytes or (M shl 5);
+ end
+ else
+ begin
+ if rd<>rm then
+ message(asmw_e_invalid_opcode_and_operands);
+
+ case oppostfix of
+ PF_S32F32,PF_U32F32,
+ PF_F32S32,PF_F32U32,
+ PF_S32F64,PF_U32F64,
+ PF_F64S32,PF_F64U32:
+ begin
+ if not (oper[2]^.val in [1..32]) then
+ message1(asmw_e_invalid_opcode_and_operands, 'fbits not within 1-32');
- bytes[2] = c << 4;
+ bytes:=bytes or (1 shl 7);
+ rn:=32;
+ end;
+ PF_S16F64,PF_U16F64,
+ PF_F64S16,PF_F64U16,
+ PF_S16F32,PF_U16F32,
+ PF_F32S16,PF_F32U16:
+ begin
+ if not (oper[2]^.val in [0..16]) then
+ message1(asmw_e_invalid_opcode_and_operands, 'fbits not within 0-16');
- bytes[3] = 0;
+ rn:=16;
+ end;
+ else
+ Rn:=0;
+ message(asmw_e_invalid_opcode_and_operands);
+ end;
- c = ins->oprs[1].basereg;
+ case oppostfix of
+ PF_S16F64,PF_U16F64,
+ PF_S32F64,PF_U32F64,
+ PF_F64S16,PF_F64U16,
+ PF_F64S32,PF_F64U32:
+ begin
+ bytes:=bytes or (1 shl 8);
+ D:=(rd shr 4) and $1; Rd:=Rd and $F;
+ end;
+ else
+ begin
+ D:=rd and $1; Rd:=Rd shr 1;
+ end;
+ end;
- if (c == R_CPSR || c == R_SPSR)
- {
- if (c == R_SPSR)
- {
- bytes[1] |= 0x40;
- }
- }
- else
- {
- errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
- }
+ case oppostfix of
+ PF_U16F64,PF_U16F32,
+ PF_U32F32,PF_U32F64,
+ PF_F64U16,PF_F32U16,
+ PF_F32U32,PF_F64U32:
+ bytes:=bytes or (1 shl 16);
+ end;
- out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
+ if oppostfix in [PF_S32F32,PF_S32F64,PF_U32F32,PF_U32F64,PF_S16F32,PF_S16F64,PF_U16F32,PF_U16F64] then
+ bytes:=bytes or (1 shl 18);
- return;
+ bytes:=bytes or (Rd shl 12);
+ bytes:=bytes or (D shl 22);
- case 0x11: // MSR <psr>,Rm
- case 0x12: // MSR <psrf>,Rm
- case 0x13: // MSR <psrf>,#expression
- ++codes;
+ rn:=rn-oper[2]^.val;
- bytes[0] = c | *codes++;
+ bytes:=bytes or ((rn and $1) shl 5);
+ bytes:=bytes or ((rn and $1E) shr 1);
+ end;
+ end;
+ #$44,#$94: // VLDM/VSTM/VPUSH/VPOP
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ { set regs }
+ if ops=2 then
+ begin
+ if oper[0]^.typ=top_ref then
+ begin
+ Rn:=getsupreg(oper[0]^.ref^.index);
- bytes[1] = *codes++;
+ if oper[0]^.ref^.addressmode<>AM_OFFSET then
+ begin
+ { set W }
+ bytes:=bytes or (1 shl 21);
+ end
+ else if oppostfix in [PF_DB,PF_DBS,PF_DBD,PF_DBX] then
+ message1(asmw_e_invalid_opcode_and_operands, 'Invalid postfix without writeback');
+ end
+ else
+ begin
+ Rn:=getsupreg(oper[0]^.reg);
- bytes[2] = *codes;
+ if oppostfix in [PF_DB,PF_DBS,PF_DBD,PF_DBX] then
+ message1(asmw_e_invalid_opcode_and_operands, 'Invalid postfix without writeback');
+ end;
+ bytes:=bytes or (Rn shl 16);
- if (keep == 0x11 || keep == 0x12)
- {
- // Rm
- c = regval (&ins->oprs[1],1);
+ { Set PU bits }
+ case oppostfix of
+ PF_None,
+ PF_IA,PF_IAS,PF_IAD,PF_IAX:
+ bytes:=bytes or (1 shl 23);
+ PF_DB,PF_DBS,PF_DBD,PF_DBX:
+ bytes:=bytes or (2 shl 23);
+ end;
- bytes[3] = c;
- }
- else
- {
- int shimm;
+ case oppostfix of
+ PF_IAX,PF_DBX,PF_FDX,PF_EAX:
+ begin
+ bytes:=bytes or (1 shl 8);
+ bytes:=bytes or (1 shl 0); // Offset is odd
+ end;
+ end;
- shimm = imm_shift (ins->oprs[1].offset);
+ dp_operation:=(oper[1]^.subreg=R_SUBFD);
+ if oper[1]^.regset^=[] then
+ message1(asmw_e_invalid_opcode_and_operands, 'Regset cannot be empty');
- if (shimm == -1)
- {
- errfunc (ERR_NONFATAL, "cannot create that constant");
- }
- bytes[3] = shimm & 0xFF;
- bytes[2] |= (shimm & 0xF00) >> 8;
- }
+ rd:=0;
+ for r:=0 to 31 do
+ if r in oper[1]^.regset^ then
+ begin
+ rd:=r;
+ break;
+ end;
- c = ins->oprs[0].basereg;
-
- if ( keep == 0x11)
- {
- if ( c == R_CPSR || c == R_SPSR)
- {
- if ( c== R_SPSR)
- {
- bytes[1] |= 0x40;
- }
- }
- else
- {
- errfunc (ERR_NONFATAL, "CPSR or SPSR expected");
- }
- }
- else
- {
- if ( c == R_CPSR_FLG || c == R_SPSR_FLG)
- {
- if ( c== R_SPSR_FLG)
- {
- bytes[1] |= 0x40;
- }
- }
- else
- {
- errfunc (ERR_NONFATAL, "CPSR_flg or SPSR_flg expected");
- }
- }
- break;
+ rn:=32-rd;
+ for r:=rd+1 to 31 do
+ if not(r in oper[1]^.regset^) then
+ begin
+ rn:=r-rd;
+ break;
+ end;
- case 0x14: // MUL Rd,Rm,Rs
- case 0x15: // MULA Rd,Rm,Rs,Rn
- ++codes;
+ if dp_operation then
+ begin
+ bytes:=bytes or (1 shl 8);
- bytes[0] = c | *codes++;
+ bytes:=bytes or (rn*2);
- bytes[1] = *codes++;
+ bytes:=bytes or ((rd and $F) shl 12);
+ bytes:=bytes or (((rd and $10) shr 4) shl 22);
+ end
+ else
+ begin
+ bytes:=bytes or rn;
- bytes[3] = *codes;
+ bytes:=bytes or ((rd and $1) shl 22);
+ bytes:=bytes or (((rd and $1E) shr 1) shl 12);
+ end;
+ end
+ else { VPUSH/VPOP }
+ begin
+ dp_operation:=(oper[0]^.subreg=R_SUBFD);
+ if oper[0]^.regset^=[] then
+ message1(asmw_e_invalid_opcode_and_operands, 'Regset cannot be empty');
- // Rd
- bytes[1] |= regval (&ins->oprs[0],1);
- if (has_S_code)
- bytes[1] |= 0x10;
+ rd:=0;
+ for r:=0 to 31 do
+ if r in oper[0]^.regset^ then
+ begin
+ rd:=r;
+ break;
+ end;
- // Rm
- bytes[3] |= regval (&ins->oprs[1],1);
+ rn:=32-rd;
+ for r:=rd+1 to 31 do
+ if not(r in oper[0]^.regset^) then
+ begin
+ rn:=r-rd;
+ break;
+ end;
- // Rs
- bytes[2] = regval (&ins->oprs[2],1);
+ if dp_operation then
+ begin
+ bytes:=bytes or (1 shl 8);
- if (keep == 0x15)
- {
- bytes[2] |= regval (&ins->oprs[3],1) << 4;
- }
- break;
+ bytes:=bytes or (rn*2);
- case 0x16: // SMLAL RdHi,RdLo,Rm,Rs
- ++codes;
+ bytes:=bytes or ((rd and $F) shl 12);
+ bytes:=bytes or (((rd and $10) shr 4) shl 22);
+ end
+ else
+ begin
+ bytes:=bytes or rn;
- bytes[0] = c | *codes++;
+ bytes:=bytes or ((rd and $1) shl 22);
+ bytes:=bytes or (((rd and $1E) shr 1) shl 12);
+ end;
+ end;
+ end;
+ #$45,#$95: // VLDR/VSTR
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ { set regs }
+ rd:=getmmreg(oper[0]^.reg);
- bytes[1] = *codes++;
+ if getsubreg(oper[0]^.reg)=R_SUBFD then
+ begin
+ bytes:=bytes or (1 shl 8);
- bytes[3] = *codes;
+ bytes:=bytes or ((rd and $F) shl 12);
+ bytes:=bytes or (((rd and $10) shr 4) shl 22);
+ end
+ else
+ begin
+ bytes:=bytes or (((rd and $1E) shr 1) shl 12);
+ bytes:=bytes or ((rd and $1) shl 22);
+ end;
- // RdHi
- bytes[1] |= regval (&ins->oprs[1],1);
- if (has_S_code)
- bytes[1] |= 0x10;
+ { set ref }
+ bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+ if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
+ begin
+ { set offset }
+ offset:=0;
+ currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
+ if assigned(currsym) then
+ offset:=currsym.offset-insoffset-8;
+ offset:=offset+oper[1]^.ref^.offset;
- // RdLo
- bytes[2] = regval (&ins->oprs[0],1) << 4;
- // Rm
- bytes[3] |= regval (&ins->oprs[2],1);
+ offset:=offset div 4;
- // Rs
- bytes[2] |= regval (&ins->oprs[3],1);
+ if offset>=0 then
+ begin
+ { set U flag }
+ bytes:=bytes or (1 shl 23);
+ bytes:=bytes or offset
+ end
+ else
+ begin
+ offset:=-offset;
+ bytes:=bytes or offset
+ end;
+ end
+ else
+ message(asmw_e_invalid_opcode_and_operands);
+ end;
+ #$46: { System instructions }
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ { set regs }
+ if (oper[0]^.typ=top_modeflags) then
+ begin
+ if mfA in oper[0]^.modeflags then bytes:=bytes or (1 shl 8);
+ if mfI in oper[0]^.modeflags then bytes:=bytes or (1 shl 7);
+ if mfF in oper[0]^.modeflags then bytes:=bytes or (1 shl 6);
+ end;
- break;
+ if (ops=2) then
+ bytes:=bytes or (oper[1]^.val and $1F)
+ else if (ops=1) and
+ (oper[0]^.typ=top_const) then
+ bytes:=bytes or (oper[0]^.val and $1F);
+ end;
+ #$60: { Thumb }
+ begin
+ bytelen:=2;
+ bytes:=0;
+
+ { set opcode }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+ bytes:=bytes or ord(insentry^.code[2]);
+ { set regs }
+ if ops=2 then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 3);
+ if (oper[1]^.typ=top_reg) then
+ bytes:=bytes or ((getsupreg(oper[1]^.reg) and $7) shl 6)
+ else
+ bytes:=bytes or ((oper[1]^.val and $1F) shl 6);
+ end
+ else if ops=3 then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
+ if (oper[2]^.typ=top_reg) then
+ bytes:=bytes or ((getsupreg(oper[2]^.reg) and $7) shl 6)
+ else
+ bytes:=bytes or ((oper[2]^.val and $1F) shl 6);
+ end
+ else if ops=1 then
+ begin
+ if oper[0]^.typ=top_const then
+ bytes:=bytes or (oper[0]^.val and $FF);
+ end;
+ end;
+ #$61: { Thumb }
+ begin
+ bytelen:=2;
+ bytes:=0;
+
+ { set opcode }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+ bytes:=bytes or ord(insentry^.code[2]);
+ { set regs }
+ if ops=2 then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+ bytes:=bytes or ((getsupreg(oper[0]^.reg) and $8) shr 3) shl 7;
- case 0x17: // LDR Rd, expression
- ++codes;
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
+ end
+ else if ops=1 then
+ begin
+ if oper[0]^.typ=top_const then
+ bytes:=bytes or (oper[0]^.val and $FF);
+ end;
+ end;
+ #$62..#$63: { Thumb branches }
+ begin
+ bytelen:=2;
+ bytes:=0;
- bytes[0] = c | *codes++;
+ { set opcode }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+ bytes:=bytes or ord(insentry^.code[2]);
- bytes[1] = *codes++;
+ if insentry^.code[0]=#$63 then
+ bytes:=bytes or (CondVal[condition] shl 8);
- // Rd
- bytes[2] = regval (&ins->oprs[0],1) << 4;
- if (has_B_code)
- bytes[1] |= 0x40;
- if (has_T_code)
- {
- errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
- }
- if (has_W_code)
- {
- errfunc (ERR_NONFATAL, "'!' not allowed");
- }
+ if oper[0]^.typ=top_const then
+ begin
+ if insentry^.code[0]=#$63 then
+ bytes:=bytes or (((oper[0]^.val shr 1)-1) and $FF)
+ else
+ bytes:=bytes or (((oper[0]^.val shr 1)-1) and $3FF);
+ end
+ else if oper[0]^.typ=top_reg then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 3);
+ end
+ else if oper[0]^.typ=top_ref then
+ begin
+ offset:=0;
+ currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
+ if assigned(currsym) then
+ offset:=currsym.offset-insoffset-8;
+ offset:=offset+oper[0]^.ref^.offset;
+
+ if insentry^.code[0]=#$63 then
+ bytes:=bytes or (((offset+4) shr 1) and $FF)
+ else
+ bytes:=bytes or (((offset+4) shr 1) and $7FF);
+ end
+ end;
+ #$64: { Thumb: Special encodings }
+ begin
+ bytelen:=2;
+ bytes:=0;
- // Rn - implicit R15
- bytes[1] |= 0xF;
+ { set opcode }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+ bytes:=bytes or ord(insentry^.code[2]);
- if (ins->oprs[1].segment != segment)
- {
- errfunc (ERR_NONFATAL, "label not in same segment");
- }
- data = ins->oprs[1].offset - (offset + 8);
+ case opcode of
+ A_SUB:
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+ if (ops=3) and
+ (oper[2]^.typ=top_const) then
+ bytes:=bytes or ((oper[2]^.val shr 2) and $7F)
+ else if (ops=2) and
+ (oper[1]^.typ=top_const) then
+ bytes:=bytes or ((oper[1]^.val shr 2) and $7F);
+ end;
+ A_MUL:
+ if (ops in [2,3]) then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
+ end;
+ A_ADD:
+ begin
+ if ops=2 then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl $3);
+ end
+ else if (oper[0]^.reg<>NR_STACK_POINTER_REG) and
+ (oper[2]^.typ=top_const) then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) and $7) shl 8;
+ bytes:=bytes or ((oper[2]^.val shr 2) and $7F);
+ end
+ else if (oper[0]^.reg<>NR_STACK_POINTER_REG) and
+ (oper[2]^.typ=top_reg) then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+ bytes:=bytes or ((getsupreg(oper[0]^.reg) and $8) shr 3) shl 7;
+ end
+ else
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+ bytes:=bytes or ((oper[2]^.val shr 2) and $7F);
+ end;
+ end;
+ end;
+ end;
+ #$65: { Thumb load/store }
+ begin
+ bytelen:=2;
+ bytes:=0;
+
+ { set opcode }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+ bytes:=bytes or ord(insentry^.code[2]);
+ { set regs }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+ bytes:=bytes or (getsupreg(oper[1]^.ref^.base) shl 3);
+ bytes:=bytes or (getsupreg(oper[1]^.ref^.index) shl 6);
+ end;
+ #$66: { Thumb load/store }
+ begin
+ bytelen:=2;
+ bytes:=0;
+
+ { set opcode }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+ bytes:=bytes or ord(insentry^.code[2]);
+ { set regs }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+ bytes:=bytes or (getsupreg(oper[1]^.ref^.base) shl 3);
+ bytes:=bytes or (((oper[1]^.ref^.offset shr ord(insentry^.code[3])) and $1F) shl 6);
+ end;
+ #$67: { Thumb load/store }
+ begin
+ bytelen:=2;
+ bytes:=0;
+
+ { set opcode }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+ bytes:=bytes or ord(insentry^.code[2]);
+ { set regs }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+ if oper[1]^.typ=top_ref then
+ bytes:=bytes or ((oper[1]^.ref^.offset shr ord(insentry^.code[3])) and $FF)
+ else
+ bytes:=bytes or ((oper[1]^.val shr ord(insentry^.code[3])) and $FF);
+ end;
+ #$68: { Thumb CB[N]Z }
+ begin
+ bytelen:=2;
+ bytes:=0;
- if (data < 0)
- {
- data = -data;
- }
- else
- {
- bytes[1] |= 0x80;
- }
+ { set opcode }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+ { set opers }
+ bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
- if (data >= 0x1000)
- {
- errfunc (ERR_NONFATAL, "too long offset");
- }
+ if oper[1]^.typ=top_ref then
+ begin
+ offset:=0;
+ currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
+ if assigned(currsym) then
+ offset:=currsym.offset-insoffset-8;
+ offset:=offset+oper[1]^.ref^.offset;
+
+ offset:=offset div 2;
+ end
+ else
+ offset:=oper[1]^.val div 2;
- bytes[2] |= ((data & 0xF00) >> 8);
- bytes[3] = data & 0xFF;
- break;
+ bytes:=bytes or ((offset) and $1F) shl 3;
+ bytes:=bytes or ((offset shr 5) and 1) shl 9;
+ end;
+ #$69: { Thumb: Push/Pop/Stm/Ldm }
+ begin
+ bytelen:=2;
+ bytes:=0;
- case 0x18: // LDR Rd, [Rn]
- ++codes;
+ { set opcode }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
- bytes[0] = c | *codes++;
+ case opcode of
+ A_PUSH:
+ begin
+ for r:=0 to 7 do
+ if r in oper[0]^.regset^ then
+ bytes:=bytes or (1 shl r);
+ if RS_R14 in oper[0]^.regset^ then
+ bytes:=bytes or (1 shl 8);
+ end;
+ A_POP:
+ begin
+ for r:=0 to 7 do
+ if r in oper[0]^.regset^ then
+ bytes:=bytes or (1 shl r);
+ if RS_R15 in oper[0]^.regset^ then
+ bytes:=bytes or (1 shl 8);
+ end;
+ A_STM:
+ begin
+ for r:=0 to 7 do
+ if r in oper[1]^.regset^ then
+ bytes:=bytes or (1 shl r);
- bytes[1] = *codes++;
+ if oper[0]^.typ=top_ref then
+ bytes:=bytes or (getsupreg(oper[0]^.ref^.base) shl 8)
+ else
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+ end;
+ A_LDM:
+ begin
+ for r:=0 to 7 do
+ if r in oper[1]^.regset^ then
+ bytes:=bytes or (1 shl r);
- // Rd
- bytes[2] = regval (&ins->oprs[0],1) << 4;
- if (has_B_code)
- bytes[1] |= 0x40;
- if (has_T_code)
- {
- bytes[1] |= 0x20; // write-back
- }
- else
- {
- bytes[0] |= 0x01; // implicit pre-index mode
- }
+ if oper[0]^.typ=top_ref then
+ bytes:=bytes or (getsupreg(oper[0]^.ref^.base) shl 8)
+ else
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+ end;
+ end;
+ end;
+ #$6A: { Thumb: IT }
+ begin
+ bytelen:=2;
+ bytes:=0;
- if (has_W_code)
- {
- bytes[1] |= 0x20; // write-back
- }
+ { set opcode }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 0);
- // Rn
- c = regval (&ins->oprs[1],1);
- bytes[1] |= c;
+ bytes:=bytes or (CondVal[oper[0]^.cc] shl 4);
- if (c == 0x15) // R15
- data = -8;
- else
- data = 0;
+ i_field:=(bytes shr 4) and 1;
+ i_field:=(i_field shl 1) or i_field;
+ i_field:=(i_field shl 2) or i_field;
- if (data < 0)
- {
- data = -data;
- }
- else
- {
- bytes[1] |= 0x80;
- }
+ bytes:=bytes or ((i_field and ord(insentry^.code[3])) xor (ord(insentry^.code[3]) shr 4));
+ end;
+ #$6B: { Thumb: Data processing (misc) }
+ begin
+ bytelen:=2;
+ bytes:=0;
+
+ { set opcode }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+ bytes:=bytes or ord(insentry^.code[2]);
+ { set regs }
+ if ops>=2 then
+ begin
+ if oper[1]^.typ=top_const then
+ begin
+ bytes:=bytes or ((getsupreg(oper[0]^.reg) and $7) shl 8);
+ bytes:=bytes or (oper[1]^.val and $FF);
+ end
+ else if oper[1]^.typ=top_reg then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
+ end;
+ end
+ else if ops=1 then
+ begin
+ if oper[0]^.typ=top_const then
+ bytes:=bytes or (oper[0]^.val and $FF);
+ end;
+ end;
+ #$6C: { Thumb: CPS }
+ begin
+ bytelen:=2;
+ bytes:=0;
- bytes[2] |= ((data & 0xF00) >> 8);
- bytes[3] = data & 0xFF;
- break;
-
- case 0x19: // LDR Rd, [Rn,#expression]
- case 0x20: // LDR Rd, [Rn,Rm]
- case 0x21: // LDR Rd, [Rn,Rm,shift]
- ++codes;
-
- bytes[0] = c | *codes++;
-
- bytes[1] = *codes++;
-
- // Rd
- bytes[2] = regval (&ins->oprs[0],1) << 4;
- if (has_B_code)
- bytes[1] |= 0x40;
-
- // Rn
- c = regval (&ins->oprs[1],1);
- bytes[1] |= c;
-
- if (ins->oprs[ins->operands-1].bracket) // FIXME: Bracket on last operand -> pre-index <--
- {
- bytes[0] |= 0x01; // pre-index mode
- if (has_W_code)
- {
- bytes[1] |= 0x20;
- }
- if (has_T_code)
- {
- errfunc (ERR_NONFATAL, "'T' not allowed in pre-index mode");
- }
- }
- else
- {
- if (has_T_code) // Forced write-back in post-index mode
- {
- bytes[1] |= 0x20;
- }
- if (has_W_code)
- {
- errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
- }
- }
+ { set opcode }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 8);
+ bytes:=bytes or ord(insentry^.code[2]);
- if (keep == 0x19)
- {
- data = ins->oprs[2].offset;
+ if mfA in oper[0]^.modeflags then bytes:=bytes or (1 shl 2);
+ if mfI in oper[0]^.modeflags then bytes:=bytes or (1 shl 1);
+ if mfF in oper[0]^.modeflags then bytes:=bytes or (1 shl 0);
+ end;
+ #$80: { Thumb-2: Dataprocessing }
+ begin
+ bytes:=0;
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
- if (data < 0)
- {
- data = -data;
- }
- else
- {
- bytes[1] |= 0x80;
- }
+ if ops=1 then
+ begin
+ if oper[0]^.typ=top_reg then
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16)
+ else if oper[0]^.typ=top_const then
+ bytes:=bytes or (oper[0]^.val and $F);
+ end
+ else if (ops=2) and
+ (opcode in [A_CMP,A_CMN,A_TEQ,A_TST]) then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
+
+ if oper[1]^.typ=top_const then
+ encodethumbimm(oper[1]^.val)
+ else if oper[1]^.typ=top_reg then
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
+ end
+ else if (ops=3) and
+ (opcode in [A_CMP,A_CMN,A_TEQ,A_TST]) then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
+
+ if oper[2]^.typ=top_shifterop then
+ setthumbshift(2)
+ else if oper[2]^.typ=top_reg then
+ bytes:=bytes or (getsupreg(oper[2]^.reg) shl 12);
+ end
+ else if (ops=2) and
+ (opcode in [A_REV,A_RBIT,A_REV16,A_REVSH,A_CLZ]) then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
+ end
+ else if ops=2 then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
+
+ if oper[1]^.typ=top_const then
+ encodethumbimm(oper[1]^.val)
+ else if oper[1]^.typ=top_reg then
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
+ end
+ else if ops=3 then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
+
+ if oper[2]^.typ=top_const then
+ encodethumbimm(oper[2]^.val)
+ else if oper[2]^.typ=top_reg then
+ bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
+ end
+ else if ops=4 then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
+ bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
+
+ if oper[3]^.typ=top_shifterop then
+ setthumbshift(3)
+ else if oper[3]^.typ=top_reg then
+ bytes:=bytes or (getsupreg(oper[3]^.reg) shl 12);
+ end;
- if (data >= 0x1000)
- {
- errfunc (ERR_NONFATAL, "too long offset");
- }
+ if oppostfix=PF_S then
+ bytes:=bytes or (1 shl 20)
+ else if oppostfix=PF_X then
+ bytes:=bytes or (1 shl 4)
+ else if oppostfix=PF_R then
+ bytes:=bytes or (1 shl 4);
+ end;
+ #$81: { Thumb-2: Dataprocessing misc }
+ begin
+ bytes:=0;
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
- bytes[2] |= ((data & 0xF00) >> 8);
- bytes[3] = data & 0xFF;
- }
- else
- {
- if (ins->oprs[2].minus == 0)
- {
- bytes[1] |= 0x80;
- }
- c = regval (&ins->oprs[2],1);
- bytes[3] = c;
-
- if (keep == 0x21)
- {
- c = ins->oprs[3].offset;
- if (c > 0x1F)
- {
- errfunc (ERR_NONFATAL, "too large shiftvalue");
- c = c & 0x1F;
- }
-
- bytes[2] |= c >> 1;
- if (c & 0x01)
- {
- bytes[3] |= 0x80;
- }
- bytes[3] |= shiftval (&ins->oprs[3]) << 5;
- }
- }
+ if ops=3 then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
- break;
+ if oper[2]^.typ=top_const then
+ begin
+ bytes:=bytes or (oper[2]^.val and $FF);
+ bytes:=bytes or ((oper[2]^.val and $700) shr 8) shl 12;
+ bytes:=bytes or ((oper[2]^.val and $800) shr 11) shl 26;
+ end;
+ end
+ else if ops=2 then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
- case 0x22: // LDRH Rd, expression
- ++codes;
+ offset:=0;
+ if oper[1]^.typ=top_const then
+ begin
+ offset:=oper[1]^.val;
+ end
+ else if oper[1]^.typ=top_ref then
+ begin
+ currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
+ if assigned(currsym) then
+ offset:=currsym.offset-insoffset-8;
+ offset:=offset+oper[1]^.ref^.offset;
- bytes[0] = c | 0x01; // Implicit pre-index
+ offset:=offset;
+ end;
- bytes[1] = *codes++;
+ bytes:=bytes or (offset and $FF);
+ bytes:=bytes or ((offset and $700) shr 8) shl 12;
+ bytes:=bytes or ((offset and $800) shr 11) shl 26;
+ bytes:=bytes or ((offset and $F000) shr 12) shl 16;
+ end;
- // Rd
- bytes[2] = regval (&ins->oprs[0],1) << 4;
+ if oppostfix=PF_S then
+ bytes:=bytes or (1 shl 20);
+ end;
+ #$82: { Thumb-2: Shifts }
+ begin
+ bytes:=0;
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
- // Rn - implicit R15
- bytes[1] |= 0xF;
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+ if oper[1]^.typ=top_reg then
+ begin
+ offset:=2;
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
+ end
+ else
+ begin
+ offset:=1;
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 0);
+ end;
- if (ins->oprs[1].segment != segment)
- {
- errfunc (ERR_NONFATAL, "label not in same segment");
- }
+ if oper[offset]^.typ=top_const then
+ begin
+ bytes:=bytes or (oper[offset]^.val and $3) shl 6;
+ bytes:=bytes or (oper[offset]^.val and $1C) shl 10;
+ end
+ else if oper[offset]^.typ=top_reg then
+ bytes:=bytes or (getsupreg(oper[offset]^.reg) shl 16);
- data = ins->oprs[1].offset - (offset + 8);
+ if (ops>=(offset+2)) and
+ (oper[offset+1]^.typ=top_const) then
+ bytes:=bytes or (oper[offset+1]^.val and $1F);
- if (data < 0)
- {
- data = -data;
- }
- else
- {
- bytes[1] |= 0x80;
- }
+ if oppostfix=PF_S then
+ bytes:=bytes or (1 shl 20);
+ end;
+ #$84: { Thumb-2: Shifts(width-1) }
+ begin
+ bytes:=0;
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
- if (data >= 0x100)
- {
- errfunc (ERR_NONFATAL, "too long offset");
- }
- bytes[3] = *codes++;
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+ if oper[1]^.typ=top_reg then
+ begin
+ offset:=2;
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
+ end
+ else
+ offset:=1;
- bytes[2] |= ((data & 0xF0) >> 4);
- bytes[3] |= data & 0xF;
- break;
+ if oper[offset]^.typ=top_const then
+ begin
+ bytes:=bytes or (oper[offset]^.val and $3) shl 6;
+ bytes:=bytes or (oper[offset]^.val and $1C) shl 10;
+ end;
- case 0x23: // LDRH Rd, Rn
- ++codes;
+ if (ops>=(offset+2)) and
+ (oper[offset+1]^.typ=top_const) then
+ begin
+ if opcode in [A_BFI,A_BFC] then
+ i_field:=oper[offset+1]^.val+oper[offset]^.val-1
+ else
+ i_field:=oper[offset+1]^.val-1;
- bytes[0] = c | 0x01; // Implicit pre-index
+ bytes:=bytes or (i_field and $1F);
+ end;
- bytes[1] = *codes++;
+ if oppostfix=PF_S then
+ bytes:=bytes or (1 shl 20);
+ end;
+ #$83: { Thumb-2: Saturation }
+ begin
+ bytes:=0;
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
- // Rd
- bytes[2] = regval (&ins->oprs[0],1) << 4;
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+ bytes:=bytes or (oper[1]^.val and $1F);
+ bytes:=bytes or (getsupreg(oper[2]^.reg) shl 16);
- // Rn
- c = regval (&ins->oprs[1],1);
- bytes[1] |= c;
+ if ops=4 then
+ setthumbshift(3,true);
+ end;
+ #$85: { Thumb-2: Long multiplications }
+ begin
+ bytes:=0;
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
- if (c == 0x15) // R15
- data = -8;
- else
- data = 0;
+ if ops=4 then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 8);
+ bytes:=bytes or (getsupreg(oper[2]^.reg) shl 16);
+ bytes:=bytes or (getsupreg(oper[3]^.reg) shl 0);
+ end;
- if (data < 0)
- {
- data = -data;
- }
- else
- {
- bytes[1] |= 0x80;
- }
+ if oppostfix=PF_S then
+ bytes:=bytes or (1 shl 20)
+ else if oppostfix=PF_X then
+ bytes:=bytes or (1 shl 4);
+ end;
+ #$86: { Thumb-2: Extension ops }
+ begin
+ bytes:=0;
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
- if (data >= 0x100)
- {
- errfunc (ERR_NONFATAL, "too long offset");
- }
- bytes[3] = *codes++;
+ if ops=2 then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
+ end
+ else if ops=3 then
+ begin
+ if oper[2]^.typ=top_shifterop then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
+ bytes:=bytes or ((oper[2]^.shifterop^.shiftimm shr 3) shl 4);
+ end
+ else
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
+ bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
+ end;
+ end
+ else if ops=4 then
+ begin
+ if oper[3]^.typ=top_shifterop then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
+ bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
+ bytes:=bytes or ((oper[3]^.shifterop^.shiftimm shr 3) shl 4);
+ end;
+ end;
+ end;
+ #$87: { Thumb-2: PLD/PLI }
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+ { set Rn and Rd }
+ bytes:=bytes or getsupreg(oper[0]^.ref^.base) shl 16;
+ if getregtype(oper[0]^.ref^.index)=R_INVALIDREGISTER then
+ begin
+ { set offset }
+ offset:=0;
+ currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
+ if assigned(currsym) then
+ offset:=currsym.offset-insoffset-8;
+ offset:=offset+oper[0]^.ref^.offset;
+ if offset>=0 then
+ begin
+ { set U flag }
+ bytes:=bytes or (1 shl 23);
+ bytes:=bytes or (offset and $FFF);
+ end
+ else
+ begin
+ bytes:=bytes or ($3 shl 10);
- bytes[2] |= ((data & 0xF0) >> 4);
- bytes[3] |= data & 0xF;
- break;
+ offset:=-offset;
+ bytes:=bytes or (offset and $FF);
+ end;
+ end
+ else
+ begin
+ bytes:=bytes or getsupreg(oper[0]^.ref^.index);
+ { set shift }
+ with oper[0]^.ref^ do
+ if shiftmode=SM_LSL then
+ bytes:=bytes or ((shiftimm and $1F) shl 4);
+ end;
+ end;
+ #$88: { Thumb-2: LDR/STR }
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or (ord(insentry^.code[4]) shl 0);
+ { set Rn and Rd }
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+ bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+ if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
+ begin
+ { set offset }
+ offset:=0;
+ currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
+ if assigned(currsym) then
+ offset:=currsym.offset-insoffset-8;
+ offset:=(offset+oper[1]^.ref^.offset) shr ord(insentry^.code[5]);
+ if offset>=0 then
+ begin
+ if not (opcode in [A_LDRT,A_LDRSBT,A_LDRSHT,A_LDRBT,A_LDRHT]) then
+ bytes:=bytes or (1 shl 23);
+ { set U flag }
+ if (oper[1]^.ref^.addressmode<>AM_OFFSET) then
+ bytes:=bytes or (1 shl 9);
+ bytes:=bytes or offset
+ end
+ else
+ begin
+ bytes:=bytes or (1 shl 11);
- case 0x24: // LDRH Rd, Rn, expression
- case 0x25: // LDRH Rd, Rn, Rm
- ++codes;
+ offset:=-offset;
+ bytes:=bytes or offset
+ end;
+ end
+ else
+ begin
+ { set I flag }
+ bytes:=bytes or (1 shl 25);
+ bytes:=bytes or getsupreg(oper[1]^.ref^.index);
+ { set shift }
+ with oper[1]^.ref^ do
+ if shiftmode<>SM_None then
+ bytes:=bytes or ((shiftimm and $1F) shl 4);
+ end;
- bytes[0] = c;
+ if not (opcode in [A_LDRT,A_LDRSBT,A_LDRSHT,A_LDRBT,A_LDRHT]) then
+ begin
+ { set W bit }
+ if oper[1]^.ref^.addressmode<>AM_OFFSET then
+ bytes:=bytes or (1 shl 8);
+ { set P bit if necessary }
+ if oper[1]^.ref^.addressmode<>AM_POSTINDEXED then
+ bytes:=bytes or (1 shl 10);
+ end;
+ end;
+ #$89: { Thumb-2: LDRD/STRD }
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or (ord(insentry^.code[4]) shl 0);
+ { set Rn and Rd }
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+ bytes:=bytes or getsupreg(oper[1]^.reg) shl 8;
+ bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
+ if getregtype(oper[2]^.ref^.index)=R_INVALIDREGISTER then
+ begin
+ { set offset }
+ offset:=0;
+ currsym:=objdata.symbolref(oper[2]^.ref^.symbol);
+ if assigned(currsym) then
+ offset:=currsym.offset-insoffset-8;
+ offset:=(offset+oper[2]^.ref^.offset) div 4;
+ if offset>=0 then
+ begin
+ { set U flag }
+ bytes:=bytes or (1 shl 23);
+ bytes:=bytes or offset
+ end
+ else
+ begin
+ offset:=-offset;
+ bytes:=bytes or offset
+ end;
+ end
+ else
+ begin
+ message(asmw_e_invalid_opcode_and_operands);
+ end;
+ { set W bit }
+ if oper[2]^.ref^.addressmode<>AM_OFFSET then
+ bytes:=bytes or (1 shl 21);
+ { set P bit if necessary }
+ if oper[2]^.ref^.addressmode<>AM_POSTINDEXED then
+ bytes:=bytes or (1 shl 24);
+ end;
+ #$8A: { Thumb-2: LDREX }
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or (ord(insentry^.code[4]) shl 0);
+ { set Rn and Rd }
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+
+ if (ops=2) and (opcode in [A_LDREX]) then
+ begin
+ bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+ if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
+ begin
+ { set offset }
+ offset:=0;
+ currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
+ if assigned(currsym) then
+ offset:=currsym.offset-insoffset-8;
+ offset:=(offset+oper[1]^.ref^.offset) div 4;
+ if offset>=0 then
+ begin
+ bytes:=bytes or offset
+ end
+ else
+ begin
+ message(asmw_e_invalid_opcode_and_operands);
+ end;
+ end
+ else
+ begin
+ message(asmw_e_invalid_opcode_and_operands);
+ end;
+ end
+ else if (ops=2) then
+ begin
+ bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+ end
+ else
+ begin
+ bytes:=bytes or getsupreg(oper[1]^.reg) shl 8;
+ bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
+ end;
+ end;
+ #$8B: { Thumb-2: STREX }
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or (ord(insentry^.code[4]) shl 0);
+ { set Rn and Rd }
+ if (ops=3) and (opcode in [A_STREX]) then
+ begin
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 8;
+ bytes:=bytes or getsupreg(oper[1]^.reg) shl 12;
+ bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
+ if getregtype(oper[2]^.ref^.index)=R_INVALIDREGISTER then
+ begin
+ { set offset }
+ offset:=0;
+ currsym:=objdata.symbolref(oper[2]^.ref^.symbol);
+ if assigned(currsym) then
+ offset:=currsym.offset-insoffset-8;
+ offset:=(offset+oper[2]^.ref^.offset) div 4;
+ if offset>=0 then
+ begin
+ bytes:=bytes or offset
+ end
+ else
+ begin
+ message(asmw_e_invalid_opcode_and_operands);
+ end;
+ end
+ else
+ begin
+ message(asmw_e_invalid_opcode_and_operands);
+ end;
+ end
+ else if (ops=3) then
+ begin
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 0;
+ bytes:=bytes or getsupreg(oper[1]^.reg) shl 12;
+ bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
+ end
+ else
+ begin
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 0;
+ bytes:=bytes or getsupreg(oper[1]^.reg) shl 12;
+ bytes:=bytes or getsupreg(oper[2]^.reg) shl 8;
+ bytes:=bytes or getsupreg(oper[3]^.ref^.base) shl 16;
+ end;
+ end;
+ #$8C: { Thumb-2: LDM/STM }
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or (ord(insentry^.code[4]) shl 0);
- bytes[1] = *codes++;
+ if oper[0]^.typ=top_reg then
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16)
+ else
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.ref^.base) shl 16);
+ if oper[0]^.ref^.addressmode<>AM_OFFSET then
+ bytes:=bytes or (1 shl 21);
+ end;
- // Rd
- bytes[2] = regval (&ins->oprs[0],1) << 4;
+ for r:=0 to 15 do
+ if r in oper[1]^.regset^ then
+ bytes:=bytes or (1 shl r);
- // Rn
- c = regval (&ins->oprs[1],1);
- bytes[1] |= c;
+ case oppostfix of
+ PF_None,PF_IA,PF_FD: bytes:=bytes or ($1 shl 23);
+ PF_DB,PF_EA: bytes:=bytes or ($2 shl 23);
+ end;
+ end;
+ #$8D: { Thumb-2: BL/BLX }
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 8);
+ { set offset }
+ if oper[0]^.typ=top_const then
+ offset:=(oper[0]^.val shr 1) and $FFFFFF
+ else
+ begin
+ currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
+ if (currsym.bind<>AB_LOCAL) and (currsym.objsection<>objdata.CurrObjSec) then
+ begin
+ objdata.writereloc(oper[0]^.ref^.offset,0,currsym,RELOC_RELATIVE_24_THUMB);
+ offset:=$FFFFFE
+ end
+ else
+ offset:=((currsym.offset-insoffset-8) shr 1) and $FFFFFF;
+ end;
- if (ins->oprs[ins->operands-1].bracket) // FIXME: Bracket on last operand -> pre-index <--
- {
- bytes[0] |= 0x01; // pre-index mode
- if (has_W_code)
- {
- bytes[1] |= 0x20;
- }
- }
- else
- {
- if (has_W_code)
- {
- errfunc (ERR_NONFATAL, "'!' not allowed in post-index mode");
- }
- }
+ bytes:=bytes or ((offset shr 00) and $7FF) shl 0;
+ bytes:=bytes or ((offset shr 11) and $3FF) shl 16;
+ bytes:=bytes or (((offset shr 21) xor (offset shr 23) xor 1) and $1) shl 11;
+ bytes:=bytes or (((offset shr 22) xor (offset shr 23) xor 1) and $1) shl 13;
+ bytes:=bytes or ((offset shr 23) and $1) shl 26;
+ end;
+ #$8E: { Thumb-2: TBB/TBH }
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
+ { set Rn and Rm }
+ bytes:=bytes or getsupreg(oper[0]^.ref^.base) shl 16;
+
+ if getregtype(oper[0]^.ref^.index)=R_INVALIDREGISTER then
+ message(asmw_e_invalid_effective_address)
+ else
+ begin
+ bytes:=bytes or getsupreg(oper[0]^.ref^.index);
- bytes[3] = *codes++;
+ if (opcode=A_TBH) and
+ (oper[0]^.ref^.shiftmode<>SM_LSL) and
+ (oper[0]^.ref^.shiftimm<>1) then
+ message(asmw_e_invalid_effective_address);
+ end;
+ end;
+ #$8F: { Thumb-2: CPSxx }
+ begin
+ { set opcode }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
- if (keep == 0x24)
- {
- data = ins->oprs[2].offset;
+ if (oper[0]^.typ=top_modeflags) then
+ begin
+ if mfA in oper[0]^.modeflags then bytes:=bytes or (1 shl 7);
+ if mfI in oper[0]^.modeflags then bytes:=bytes or (1 shl 6);
+ if mfF in oper[0]^.modeflags then bytes:=bytes or (1 shl 5);
+ end;
- if (data < 0)
- {
- data = -data;
- }
- else
- {
- bytes[1] |= 0x80;
- }
+ if (ops=2) then
+ bytes:=bytes or (oper[1]^.val and $1F)
+ else if (ops=1) and
+ (oper[0]^.typ=top_const) then
+ bytes:=bytes or (oper[0]^.val and $1F);
+ end;
+ #$96: { Thumb-2: MSR/MRS }
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
- if (data >= 0x100)
- {
- errfunc (ERR_NONFATAL, "too long offset");
- }
+ if opcode=A_MRS then
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
- bytes[2] |= ((data & 0xF0) >> 4);
- bytes[3] |= data & 0xF;
- }
- else
- {
- if (ins->oprs[2].minus == 0)
- {
- bytes[1] |= 0x80;
- }
- c = regval (&ins->oprs[2],1);
- bytes[3] |= c;
+ case oper[1]^.reg of
+ NR_MSP: bytes:=bytes or $08;
+ NR_PSP: bytes:=bytes or $09;
- }
- break;
+ NR_IPSR: bytes:=bytes or $05;
+ NR_EPSR: bytes:=bytes or $06;
+ NR_APSR: bytes:=bytes or $00;
- case 0x26: // LDM/STM Rn, {reg-list}
- ++codes;
+ NR_PRIMASK: bytes:=bytes or $10;
+ NR_BASEPRI: bytes:=bytes or $11;
+ NR_BASEPRI_MAX: bytes:=bytes or $12;
+ NR_FAULTMASK: bytes:=bytes or $13;
+ NR_CONTROL: bytes:=bytes or $14;
+ else
+ Message(asmw_e_invalid_opcode_and_operands);
+ end;
+ end
+ else
+ begin
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
- bytes[0] = c;
+ case oper[0]^.reg of
+ NR_APSR,
+ NR_APSR_nzcvqg: bytes:=bytes or $C00;
+ NR_APSR_g: bytes:=bytes or $400;
+ NR_APSR_nzcvq: bytes:=bytes or $800;
- bytes[0] |= ( *codes >> 4) & 0xF;
- bytes[1] = ( *codes << 4) & 0xF0;
- ++codes;
+ NR_MSP: bytes:=bytes or $08;
+ NR_PSP: bytes:=bytes or $09;
- if (has_W_code)
- {
- bytes[1] |= 0x20;
- }
- if (has_F_code)
- {
- bytes[1] |= 0x40;
- }
+ NR_PRIMASK: bytes:=bytes or $10;
+ NR_BASEPRI: bytes:=bytes or $11;
+ NR_BASEPRI_MAX: bytes:=bytes or $12;
- // Rn
- bytes[1] |= regval (&ins->oprs[0],1);
+ NR_FAULTMASK: bytes:=bytes or $13;
+ NR_CONTROL: bytes:=bytes or $14;
+ else
+ Message(asmw_e_invalid_opcode_and_operands);
+ end;
+ end;
+ end;
+ #$A0: { FPA: CPDT(LDF/STF) }
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or (ord(insentry^.code[3]) shl 8);
+ bytes:=bytes or ord(insentry^.code[4]);
- data = ins->oprs[1].basereg;
+ if ops=2 then
+ begin
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+
+ bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
+ bytes:=bytes or ((oper[1]^.ref^.offset shr 2) and $FF);
+ if oper[1]^.ref^.offset>=0 then
+ bytes:=bytes or (1 shl 23);
+
+ if oper[1]^.ref^.addressmode<>AM_OFFSET then
+ bytes:=bytes or (1 shl 21);
+ if oper[1]^.ref^.addressmode=AM_PREINDEXED then
+ bytes:=bytes or (1 shl 24);
+
+ case oppostfix of
+ PF_D: bytes:=bytes or (0 shl 22) or (1 shl 15);
+ PF_E: bytes:=bytes or (1 shl 22) or (0 shl 15);
+ PF_P: bytes:=bytes or (1 shl 22) or (1 shl 15);
+ end;
+ end
+ else
+ begin
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
- bytes[2] = ((data >> 8) & 0xFF);
- bytes[3] = (data & 0xFF);
+ case oper[1]^.val of
+ 1: bytes:=bytes or (1 shl 15);
+ 2: bytes:=bytes or (1 shl 22);
+ 3: bytes:=bytes or (1 shl 22) or (1 shl 15);
+ 4: ;
+ else
+ message1(asmw_e_invalid_opcode_and_operands, 'Invalid count for LFM/SFM');
+ end;
- break;
+ bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
+ bytes:=bytes or ((oper[2]^.ref^.offset shr 2) and $FF);
+ if oper[2]^.ref^.offset>=0 then
+ bytes:=bytes or (1 shl 23);
- case 0x27: // SWP Rd, Rm, [Rn]
- ++codes;
+ if oper[2]^.ref^.addressmode<>AM_OFFSET then
+ bytes:=bytes or (1 shl 21);
+ if oper[2]^.ref^.addressmode=AM_PREINDEXED then
+ bytes:=bytes or (1 shl 24);
+ end;
+ end;
+ #$A1: { FPA: CPDO }
+ begin
+ { set instruction code }
+ bytes:=bytes or ($E shl 24);
+ bytes:=bytes or (ord(insentry^.code[1]) shl 15);
+ bytes:=bytes or ((ord(insentry^.code[2]) shr 1) shl 20);
+ bytes:=bytes or (1 shl 8);
- bytes[0] = c;
+ bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
+ if ops=2 then
+ begin
+ if oper[1]^.typ=top_reg then
+ bytes:=bytes or getsupreg(oper[1]^.reg) shl 0
+ else
+ case oper[1]^.val of
+ 0: bytes:=bytes or $8;
+ 1: bytes:=bytes or $9;
+ 2: bytes:=bytes or $A;
+ 3: bytes:=bytes or $B;
+ 4: bytes:=bytes or $C;
+ 5: bytes:=bytes or $D;
+ //0.5: bytes:=bytes or $E;
+ 10: bytes:=bytes or $F;
+ else
+ Message(asmw_e_invalid_opcode_and_operands);
+ end;
+ end
+ else
+ begin
+ bytes:=bytes or getsupreg(oper[1]^.reg) shl 16;
+ if oper[2]^.typ=top_reg then
+ bytes:=bytes or getsupreg(oper[2]^.reg) shl 0
+ else
+ case oper[2]^.val of
+ 0: bytes:=bytes or $8;
+ 1: bytes:=bytes or $9;
+ 2: bytes:=bytes or $A;
+ 3: bytes:=bytes or $B;
+ 4: bytes:=bytes or $C;
+ 5: bytes:=bytes or $D;
+ //0.5: bytes:=bytes or $E;
+ 10: bytes:=bytes or $F;
+ else
+ Message(asmw_e_invalid_opcode_and_operands);
+ end;
+ end;
- bytes[0] |= *codes++;
+ case roundingmode of
+ RM_P: bytes:=bytes or (1 shl 5);
+ RM_M: bytes:=bytes or (2 shl 5);
+ RM_Z: bytes:=bytes or (3 shl 5);
+ end;
- bytes[1] = regval (&ins->oprs[2],1);
- if (has_B_code)
- {
- bytes[1] |= 0x40;
- }
- bytes[2] = regval (&ins->oprs[0],1) << 4;
- bytes[3] = *codes++;
- bytes[3] |= regval (&ins->oprs[1],1);
- break;
+ case oppostfix of
+ PF_S: bytes:=bytes or (0 shl 19) or (0 shl 7);
+ PF_D: bytes:=bytes or (0 shl 19) or (1 shl 7);
+ PF_E: bytes:=bytes or (1 shl 19) or (0 shl 7);
+ else
+ message1(asmw_e_invalid_opcode_and_operands, 'Precision cannot be undefined');
+ end;
+ end;
+ #$A2: { FPA: CPDO }
+ begin
+ { set instruction code }
+ bytes:=bytes or (ord(insentry^.code[1]) shl 24);
+ bytes:=bytes or (ord(insentry^.code[2]) shl 16);
+ bytes:=bytes or ($11 shl 4);
- default:
- errfunc (ERR_FATAL, "unknown decoding of instruction");
+ case opcode of
+ A_FLT:
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 12);
- bytes[0] = c;
- // And a fix nibble
- ++codes;
- bytes[0] |= *codes++;
+ case roundingmode of
+ RM_P: bytes:=bytes or (1 shl 5);
+ RM_M: bytes:=bytes or (2 shl 5);
+ RM_Z: bytes:=bytes or (3 shl 5);
+ end;
- if ( *codes == 0x01) // An I bit
- {
+ case oppostfix of
+ PF_S: bytes:=bytes or (0 shl 19) or (0 shl 7);
+ PF_D: bytes:=bytes or (0 shl 19) or (1 shl 7);
+ PF_E: bytes:=bytes or (1 shl 19) or (0 shl 7);
+ else
+ message1(asmw_e_invalid_opcode_and_operands, 'Precision cannot be undefined');
+ end;
+ end;
+ A_FIX:
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+ bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
- }
- if ( *codes == 0x02) // An I bit
- {
+ case roundingmode of
+ RM_P: bytes:=bytes or (1 shl 5);
+ RM_M: bytes:=bytes or (2 shl 5);
+ RM_Z: bytes:=bytes or (3 shl 5);
+ end;
+ end;
+ A_WFS,A_RFS,A_WFC,A_RFC:
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
+ end;
+ A_CMF,A_CNF,A_CMFE,A_CNFE:
+ begin
+ bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
- }
- ++codes;
- }
- out (offset, segment, bytes, OUT_RAWDATA+4, NO_SEG, NO_SEG);
-}
+ if oper[1]^.typ=top_reg then
+ bytes:=bytes or getsupreg(oper[1]^.reg) shl 0
+ else
+ case oper[1]^.val of
+ 0: bytes:=bytes or $8;
+ 1: bytes:=bytes or $9;
+ 2: bytes:=bytes or $A;
+ 3: bytes:=bytes or $B;
+ 4: bytes:=bytes or $C;
+ 5: bytes:=bytes or $D;
+ //0.5: bytes:=bytes or $E;
+ 10: bytes:=bytes or $F;
+ else
+ Message(asmw_e_invalid_opcode_and_operands);
+ end;
+ end;
+ end;
+ end;
+ #$fe: // No written data
+ begin
+ exit;
+ end;
+ #$ff:
+ internalerror(2005091101);
+ else
+ begin
+ writeln(ord(insentry^.code[0]), ' - ', opcode);
+ internalerror(2005091102);
+ end;
+ end;
-*)
-{$endif dummy}
+ { Todo: Decide whether the code above should take care of writing data in an order that makes senes }
+ if (insentry^.code[0] in [#$80..#$96]) and (bytelen=4) then
+ bytes:=((bytes shr 16) and $FFFF) or ((bytes and $FFFF) shl 16);
- constructor tai_thumb_func.create;
- begin
- inherited create;
- typ:=ait_thumb_func;
- end;
+ { we're finished, write code }
+ objdata.writebytes(bytes,bytelen);
+ end;
begin
cai_align:=tai_align;
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;
begin
inherited create(smart);
InstrWriter := TArmInstrWriter.create(self);
+ if GenerateThumb2Code then
+ TArmInstrWriter(InstrWriter).unified_syntax:=true;
end;
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
procedure TArmGNUAssembler.WriteExtraHeader;
begin
inherited WriteExtraHeader;
- if GenerateThumb2Code then
+ if TArmInstrWriter(InstrWriter).unified_syntax then
AsmWriteLn(#9'.syntax unified');
end;
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;
var
hs : string;
first : boolean;
- r : tsuperregister;
+ r, rs : tsuperregister;
begin
case o.typ of
top_reg:
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+'^';
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
// 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:
{ 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,
{ don't edit, this file is generated from armins.dat }
(
'none',
-'abs',
-'acs',
-'asn',
-'atn',
'adc',
'add',
+'addw',
'adf',
'adr',
'and',
'bkpt',
'bx',
'cdp',
-'cmf',
-'cmfe',
'cmn',
'cmp',
+'cmf',
+'cmfe',
+'stf',
+'ldf',
+'lfm',
'clz',
-'cnf',
-'cos',
'cps',
'cpsid',
'cpsie',
-'dvf',
'eor',
-'exp',
-'fdv',
-'flt',
-'fix',
-'fml',
-'frd',
'ldc',
'ldm',
'ldrbt',
'ldrsb',
'ldrsh',
'ldrt',
-'ldf',
-'lfm',
-'lgn',
-'log',
'mcr',
+'mcr2',
+'mrc',
+'mrc2',
+'mcrr',
+'mcrr2',
+'mrrc',
+'mrrc2',
'mla',
'mov',
-'mrc',
'mrs',
'msr',
-'mnf',
-'muf',
'mul',
'mvf',
'mvn',
+'vmov',
'nop',
+'orn',
'orr',
-'rdf',
-'rfs',
-'rfc',
-'rmf',
-'rpw',
'rsb',
'rsc',
-'rsf',
-'rnd',
-'pol',
'sbc',
'sfm',
'sin',
'smlal',
'smull',
-'sqt',
-'suf',
-'stf',
'stm',
'str',
'strb',
'swi',
'swp',
'swpb',
-'tan',
'teq',
'tst',
'umlal',
'umull',
'wfs',
'ldrd',
-'mcrr',
-'mrrc',
'pld',
+'pldw',
'qadd',
'qdadd',
'qdsub',
'smlaltt',
'smlawb',
'smlawt',
+'vldm',
+'vstm',
+'vpop',
+'vpush',
+'vldr',
+'vstr',
'smulbb',
'smulbt',
'smultb',
'smulwb',
'smulwt',
'strd',
-'fabsd',
-'fabss',
-'faddd',
-'fadds',
-'fcmpd',
-'fcmped',
-'fcmpes',
-'fcmpezd',
-'fcmpezs',
-'fcmps',
-'fcmpzd',
-'fcmpzs',
-'fcpyd',
-'fcpys',
-'fcvtds',
-'fcvtsd',
-'fdivd',
-'fdivs',
-'fldd',
-'fldm',
-'flds',
-'fmacd',
-'fmacs',
-'fmdhr',
-'fmdlr',
-'fmrdh',
-'fmrdl',
-'fmrs',
-'fmrx',
-'fmscd',
-'fmscs',
-'fmsr',
-'fmstat',
-'fmuld',
-'fmuls',
-'fmxr',
-'fnegd',
-'fnegs',
-'fnmacd',
-'fnmacs',
-'fnmscd',
-'fnmscs',
-'fnmuld',
-'fnmuls',
-'fsitod',
-'fsitos',
-'fsqrtd',
-'fsqrts',
+'ldrht',
+'strht',
+'ldrsbt',
+'ldrsht',
'fstd',
'fstm',
'fsts',
-'fsubd',
-'fsubs',
-'ftosid',
-'ftosis',
-'ftouid',
-'ftouis',
-'fuitod',
-'fuitos',
-'fmdrr',
-'fmrrd',
'bfc',
'bfi',
'clrex',
'ldrexb',
'ldrexd',
'ldrexh',
+'strex',
+'strexb',
+'strexd',
+'strexh',
'mls',
-'pkh',
+'pkhbt',
+'pkhtb',
'pli',
'qadd16',
'qadd8',
'lsr',
'lsl',
'ror',
+'rrx',
+'umaal',
'shadd16',
'shadd8',
'shasx',
'ssax',
'ssub16',
'ssub8',
-'strex',
-'strexb',
-'strexd',
-'strexh',
'sxtab',
'sxtab16',
'sxtah',
+'ubfx',
+'uxtab',
+'uxtab16',
+'uxtah',
'sxtb',
'sxtb16',
+'sxth',
'uxtb',
+'uxtb16',
'uxth',
-'sxth',
'uadd16',
'uadd8',
'uasx',
-'ubfx',
'uhadd16',
'uhadd8',
'uhasx',
'uhsax',
'uhsub16',
'uhsub8',
-'umaal',
'uqadd16',
'uqadd8',
'uqasx',
'uqsax',
'uqsub16',
'uqsub8',
-'uqsad8',
-'uqsada8',
+'usad8',
+'usada8',
'usat',
'usat16',
'usax',
'usub16',
'usub8',
-'uxtab',
-'uxtab16',
-'uxtah',
-'uxtb16',
'wfe',
'wfi',
'yield',
+'fabsd',
+'fabss',
+'faddd',
+'fadds',
+'fcmpd',
+'fcmps',
+'fcmped',
+'fcmpes',
+'fcmpzd',
+'fcmpzs',
+'fcmpezd',
+'fcmpezs',
+'fcpyd',
+'fcpys',
+'fcvtds',
+'fcvtsd',
+'fdivd',
+'fdivs',
+'fldd',
+'fldm',
+'flds',
+'fmacd',
+'fmacs',
+'fmdhr',
+'fmdlr',
+'fmrdh',
+'fmrdl',
+'fmrs',
+'fmrx',
+'fmscd',
+'fmscs',
+'fmsr',
+'fmstat',
+'fmuld',
+'fmuls',
+'fmxr',
+'fnegd',
+'fnegs',
+'fnmacd',
+'fnmacs',
+'fnmscd',
+'fnmscs',
+'fnmuld',
+'fnmuls',
+'fsitod',
+'fsitos',
+'fsqrtd',
+'fsqrts',
+'fsubd',
+'fsubs',
+'ftosid',
+'ftosis',
+'ftouid',
+'ftouis',
+'fuitod',
+'fuitos',
+'fmdrr',
+'fmrrd',
'pop',
'push',
'sdiv',
'vcmp',
'vcmpe',
'vcvt',
+'vcvtr',
'vdiv',
-'vldm',
-'vldr',
-'vmov',
'vmrs',
'vmsr',
-'vmul',
'vmla',
'vmls',
+'vmul',
'vnmla',
'vnmls',
+'vnmul',
'vfma',
'vfms',
'vfnma',
'vfnms',
'vneg',
-'vnmul',
-'vpop',
-'vpush',
'vsqrt',
-'vstm',
-'vstr',
'vsub',
+'dmb',
+'isb',
+'dsb',
+'smc',
'neg',
-'svc'
+'svc',
+'bxj',
+'udf',
+'tan',
+'sqt',
+'suf',
+'rsf',
+'rnd',
+'pol',
+'rdf',
+'rfs',
+'rfc',
+'wfc',
+'rmf',
+'rpw',
+'mnf',
+'muf',
+'abs',
+'acs',
+'asn',
+'atn',
+'cnf',
+'cnfe',
+'cos',
+'dvf',
+'exp',
+'fdv',
+'flt',
+'fix',
+'fml',
+'frd',
+'lgn',
+'log'
);
attsufNONE,
attsufNONE,
attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
attsufNONE
);
[NONE]
void void none
-[ABScc]
+[ADCcc]
+reglo,reglo \x6B\x41\x40 THUMB,ARMv4T
-[ACScc]
+reg32,immshifter \x80\xF1\x40\x0\x0 THUMB32,ARMv6T2
+reg32,reg32 \x80\xEB\x40\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x80\xEB\x40\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter \x80\xF1\x40\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x80\xEB\x40\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEB\x40\x0\x0 THUMB32,WIDE,ARMv6T2
-[ASNcc]
+reg32,reg32,reg32 \4\x0\xA0 ARM32,ARMv4
+reg32,reg32,reg32,shifterop \6\x0\xA0 ARM32,ARMv4
+reg32,reg32,immshifter \7\x2\xA0 ARM32,ARMv4
-[ATNcc]
+[ADDcc]
+reg32,reg32 \x61\x44\x0 THUMB,ARMv4T
+reglo,reglo,reglo \x60\x18\x0 THUMB,ARMv4T
-[ADCcc]
-reg32,reg32,reg32 \4\x0\xA0 ARM7
-reg32,reg32,reg32,reg32 \5\x0\xA0 ARM7
-reg32,reg32,reg32,imm \6\x0\xA0 ARM7
-reg32,reg32,imm \7\x2\xA0 ARM7
+reglo,immshifter \x60\x1C\x0 THUMB,ARMv4T
+reglo,reglo,immshifter \x60\x1C\x0 THUMB,ARMv4T
+reglo,immshifter \x6B\x30\x0 THUMB,ARMv4T
-[ADDcc]
-reg32,reg32,reg32 \4\x0\x80 ARM7
-reg32,reg32,reg32,reg32 \5\x0\x80 ARM7
-reg32,reg32,reg32,imm \6\x0\x80 ARM7
-reg32,reg32,imm \7\x2\x80 ARM7
+reglo,regsp,immshifter \x64\xA8\x00 THUMB,ARMv4T
+regsp,regsp,immshifter \x64\xB0\x00 THUMB,ARMv4T
+reg32,regsp,reg32 \x64\x44\x68 THUMB,ARMv4T
+regsp,reg32 \x64\x44\x85 THUMB,ARMv4T
+
+reg32,immshifter \x80\xF1\x0\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32 \x80\xEB\x0\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x80\xEB\x0\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter \x80\xF1\x0\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32 \x80\xEB\x0\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEB\x0\x0\x0 THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,reg32 \4\x0\x80 ARM32,ARMv4
+reg32,reg32,reg32,shifterop \6\x0\x80 ARM32,ARMv4
+reg32,reg32,immshifter \7\x2\x80 ARM32,ARMv4
+
+[ADDWcc]
+reg32,reg32,immshifter \x81\xF2\x0\x0\x0 THUMB32,ARMv6T2
[ADFcc]
+fpureg,fpureg,fpureg \xA1\0\x0 ARM32,FPA
+fpureg,fpureg,immshifter \xA1\0\x0 ARM32,FPA
[ADRcc]
+;reg32,immshifter \x33\x2\x0F ARM32,ARMv4
+;reg32,imm32 \x33\x2\x0F ARM32,ARMv4
+reglo,immshifter \x67\xA0\x0\2 THUMB,ARMv4T
+reglo,memam6 \x67\xA0\x0\2 THUMB,ARMv4T
+
+reg32,imm32 \x81\xF2\xAF\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,immshifter \x81\xF2\xAF\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,memam2 \x81\xF2\xAF\x0\x0 THUMB32,WIDE,ARMv6T2
+
+reg32,memam2 \x33\x2\x0F ARM32,ARMv4
[ANDcc]
-reg32,reg32,reg32 \4\x0\x00 ARM7
-reg32,reg32,reg32,reg32 \5\x0\x00 ARM7
-reg32,reg32,reg32,imm \6\x0\x00 ARM7
-reg32,reg32,imm \7\x2\x00 ARM7
+reglo,reglo \x6B\x40\x00 THUMB,ARMv4T
+
+reg32,immshifter \x80\xF0\x0\x0\x0 THUMB32,ARMv6T2
+reg32,reg32 \x80\xEA\x0\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x80\xEA\x0\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter \x80\xF0\x0\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x80\xEA\x0\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\x0\x0\x0 THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,reg32 \x4\x0\x00 ARM32,ARMv4
+reg32,reg32,reg32,shifterop \x6\x0\x00 ARM32,ARMv4
+reg32,reg32,immshifter \x7\x2\x00 ARM32,ARMv4
[Bcc]
-mem32 \1\x0A ARM7
-imm24 \1\x0A ARM7
+imm24 \x62\xE0\x0 THUMB,ARMv4T
+immshifter \x62\xE0\x0 THUMB,ARMv4T
+mem32 \x62\xE0\x0 THUMB,ARMv4T
+
+imm24 \x63\xD0\x0 THUMB,ARMv4T
+immshifter \x63\xD0\x0 THUMB,ARMv4T
+mem32 \x63\xD0\x0 THUMB,ARMv4T
+
+imm24 \x1\x0A ARM32,ARMv4
+mem32 \x1\x0A ARM32,ARMv4
[BICcc]
-reg32,reg32,reg32 \4\x1\xC0 ARM7
-reg32,reg32,reg32,reg32 \5\x1\xC0 ARM7
-reg32,reg32,reg32,imm \6\x1\xC0 ARM7
-reg32,reg32,imm \7\x3\xC0 ARM7
+reglo,reglo \x6B\x43\x80 THUMB,ARMv4T
+
+reg32,immshifter \x80\xF0\x20\x0\x0 THUMB32,ARMv6T2
+reg32,reg32 \x80\xEA\x20\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x80\xEA\x20\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter \x80\xF0\x20\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x80\xEA\x20\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\x20\x0\x0 THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,reg32 \x6\x1\xC0 ARM32,ARMv4
+reg32,reg32,reg32,shifterop \x6\x1\xC0 ARM32,ARMv4
+reg32,reg32,immshifter \x7\x3\xC0 ARM32,ARMv4
[BLcc]
-mem32 \1\x0B ARM7
-imm24 \1\x0B ARM7
+imm24 \x8D\xF0\xD0 THUMB,THUMB32,ARMv4T
+immshifter \x8D\xF0\xD0 THUMB,THUMB32,ARMv4T
+mem32 \x8D\xF0\xD0 THUMB,THUMB32,ARMv4T
+
+imm24 \x1\x0B ARM32,ARMv4
+mem32 \x1\x0B ARM32,ARMv4
[BLX]
-mem32 \xff ARM7
-imm24 \xff ARM7
+reg32 \x62\x47\x80 THUMB,ARMv4T
+
+immshifter \x8D\xF0\xC0 THUMB32,ARMv6T2
+imm24 \x8D\xF0\xC0 THUMB32,ARMv6T2
+mem32 \x8D\xF0\xC0 THUMB32,ARMv6T2
+
+imm24 \x28\xFA ARM32,ARMv5T
+mem32 \x28\xFA ARM32,ARMv5T
+reg32 \3\x01\x2F\xFF\x30 ARM32,ARMv5T
[BKPTcc]
+immshifter \x60\xBE\x0 THUMB,ARMv5T
+imm \x31\x1\x20\x70 ARM32,ARMv5T
+immshifter \x31\x1\x20\x70 ARM32,ARMv5T
[BXcc]
-reg32 \3\x01\x2F\xFF\x10 ARM7
+reg32 \x62\x47\x0 THUMB,ARMv4T
+
+reg32 \3\x01\x2F\xFF\x10 ARM32,ARMv4T
[CDP]
-reg8,reg8 \300\1\x10\101 ARM7
+reg8,reg8 \300\1\x10\101 ARM32,ARMv4
-[CMFcc]
+[CMNcc]
+reglo,reglo \x6B\x42\xC0 THUMB,ARMv4T
-[CMFEcc]
+reg32,immshifter \x80\xF1\x10\x0F\x00 THUMB32,ARMv6T2
+reg32,reg32 \x80\xEB\x10\x0F\x00 THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x80\xEB\x10\x0F\x00 THUMB32,WIDE,ARMv6T2
-[CMNcc]
-reg32,reg32 \xC\x1\x60 ARM7
-reg32,reg32,reg32 \xD\x1\x60 ARM7
-reg32,reg32,imm \xE\x1\x60 ARM7
-reg32,imm \xF\x3\x60 ARM7
+reg32,reg32 \xC\x1\x60 ARM32,ARMv4
+reg32,reg32,shifterop \xE\x1\x60 ARM32,ARMv4
+reg32,immshifter \xF\x1\x60 ARM32,ARMv4
[CMPcc]
-reg32,reg32 \xC\x1\x40 ARM7
-reg32,reg32,reg32 \xD\x1\x40 ARM7
-reg32,reg32,imm \xE\x1\x40 ARM7
-reg32,imm \xF\x3\x40 ARM7
+reglo,reglo \x6B\x42\x80 THUMB,ARMv4T
+reg32,reg32 \x61\x45\x0 THUMB,ARMv4T
-[CLZcc]
-reg32,reg32 \x27\x01\x01 ARM7
+reglo,immshifter \x6B\x28\x0 THUMB,ARMv4T
-[CNFcc]
+reg32,immshifter \x80\xF1\xB0\x0F\x00 THUMB32,WIDE,ARMv6T2
+reg32,reg32 \x80\xEB\xB0\x0F\x00 THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x80\xEB\xB0\x0F\x00 THUMB32,WIDE,ARMv6T2
-[COScc]
+reg32,reg32 \xC\x1\x40 ARM32,ARMv4
+reg32,reg32,shifterop \xE\x1\x40 ARM32,ARMv4
+reg32,immshifter \xF\x3\x40 ARM32,ARMv4
-[CPS]
-[CPSID]
-[CPSIE]
+[CMFcc]
+fpureg,fpureg \xA2\xE\x90 ARM32,FPA
+fpureg,immshifter \xA2\xE\x90 ARM32,FPA
-[DVFcc]
+[CMFEcc]
+fpureg,fpureg \xA2\xE\xC0 ARM32,FPA
+fpureg,immshifter \xA2\xE\xC0 ARM32,FPA
-[EORcc]
-reg32,reg32,reg32 \4\x0\x20 ARM7
-reg32,reg32,reg32,reg32 \5\x0\x20 ARM7
-reg32,reg32,reg32,imm \6\x0\x20 ARM7
-reg32,reg32,imm \7\x2\x20 ARM7
+[STFcc]
+fpureg,memam2 \xA0\xC\x00\x1\x0 ARM32,FPA
-[EXPcc]
+[LDFcc]
+fpureg,memam2 \xA0\xC\x10\x1\x0 ARM32,FPA
-[FDVcc]
+[LFMcc]
+fpureg,imm32,memam2 \xA0\xC\x10\x2\x0 ARM32,FPA
+fpureg,immshifter,memam2 \xA0\xC\x10\x2\x0 ARM32,FPA
-[FLTcc]
+[CLZcc]
+reg32,reg32 \x80\xFA\xB0\xF0\x80 THUMB32,ARMv6T2
+reg32,reg32 \x32\x01\x6F\xF\x10 ARM32,ARMv4
-[FIXcc]
+[CPS]
+immshifter \x8F\xF3\xAF\x81\x00 THUMB32,ARMv6T2
+immshifter \x46\xF1\x2\x0\x0 ARM32,ARMv6
-[FMLcc]
+[CPSID]
+modeflags \x6C\xB6\x70 THUMB,ARMv6
+modeflags \x8F\xF3\xAF\x86\x00 THUMB32,WIDE,ARMv6T2
+modeflags,immshifter \x8F\xF3\xAF\x87\x00 THUMB32,WIDE,ARMv6T2
+modeflags \x46\xF1\xC\x0\x0 ARM32,ARMv6
+modeflags,immshifter \x46\xF1\xE\x0\x0 ARM32,ARMv6
-[FRDcc]
+[CPSIE]
+modeflags \x6C\xB6\x60 THUMB,ARMv6
+modeflags \x8F\xF3\xAF\x84\x00 THUMB32,WIDE,ARMv6T2
+modeflags,immshifter \x8F\xF3\xAF\x85\x00 THUMB32,WIDE,ARMv6T2
+modeflags \x46\xF1\x8\x0\x0 ARM32,ARMv6
+modeflags,immshifter \x46\xF1\xA\x0\x0 ARM32,ARMv6
+
+[EORcc]
+reglo,reglo \x6B\x40\x40 THUMB,ARMv4T
+
+reg32,immshifter \x80\xF0\x80\x0\x0 THUMB32,ARMv6T2
+reg32,reg32 \x80\xEA\x80\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x80\xEA\x80\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter \x80\xF0\x80\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x80\xEA\x80\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\x80\x0\x0 THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,reg32 \4\x0\x20 ARM32,ARMv4
+reg32,reg32,reg32,shifterop \6\x0\x20 ARM32,ARMv4
+reg32,reg32,immshifter \7\x2\x20 ARM32,ARMv4
[LDC]
-reg32,reg32 \321\300\1\x11\101 ARM7
+reg32,reg32 \321\300\1\x11\101 ARM32,ARMv4
[LDMcc]
-memam4,reglist \x26\x81 ARM7
+memam4,reglist \x69\xC8 THUMB,ARMv4T
+reglo,reglist \x69\xC8 THUMB,ARMv4T
+
+memam4,reglist \x8C\xE8\x10\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reglist \x8C\xE8\x10\x0\x0 THUMB32,WIDE,ARMv6T2
+
+memam4,reglist \x26\x81 ARM32,ARMv4
+reg32,reglist \x26\x81 ARM32,ARMv4
[LDRBTcc]
+reg32,memam2 \x88\xF8\x10\xE\x0\0 THUMB32,ARMv6T2
+reg32,memam2 \x17\x04\x70 ARM32,ARMv4
+reg32,immshifter \x17\x04\x70 ARM32,ARMv4
[LDRBcc]
-reg32,memam2 \x17\x07\x10 ARM7
+reglo,memam3 \x65\x5C\x0\0 THUMB,ARMv4T
+reglo,memam4 \x66\x78\x0\0 THUMB,ARMv4T
+reg32,memam2 \x88\xF8\x10\x0\x0\0 THUMB32,WIDE,ARMv6T2
+reg32,memam2 \x17\x04\x50 ARM32,ARMv4
[LDRcc]
-reg32,memam2 \x17\x05\x10 ARM7
-; reg32,imm32 \x17\x05\x10 ARM7
-; reg32,reg32 \x18\x04\x10 ARM7
-; reg32,reg32,imm32 \x19\x04\x10 ARM7
-; reg32,reg32,reg32 \x20\x06\x10 ARM7
-; reg32,reg32,reg32,imm32 \x21\x06\x10 ARM7
+reglo,memam3 \x65\x58\x0\2 THUMB,ARMv4T
+reglo,memam4 \x66\x68\x0\2 THUMB,ARMv4T
+reglo,memam5 \x67\x98\x0\2 THUMB,ARMv4T
+reglo,memam6 \x67\x48\x0\2 THUMB,ARMv4T
+reg32,memam2 \x88\xF8\x50\x0\x0\0 THUMB32,WIDE,ARMv6T2
+reg32,memam2 \x17\x04\x10 ARM32,ARMv4
[LDRHcc]
-reg32,imm32 \x22\x50\xB0 ARM7
-reg32,reg32 \x23\x50\xB0 ARM7
-reg32,reg32,imm32 \x24\x50\xB0 ARM7
-reg32,reg32,reg32 \x25\x10\xB0 ARM7
+reglo,memam3 \x65\x5A\x0\1 THUMB,ARMv4T
+reglo,memam4 \x66\x88\x0\1 THUMB,ARMv4T
+reg32,memam2 \x88\xF8\x30\x0\x0\0 THUMB32,WIDE,ARMv6T2
+reg32,memam2 \x22\x10\xB0 ARM32,ARMv4
[LDRSBcc]
-reg32,imm32 \x22\x50\xD0 ARM7
-reg32,reg32 \x23\x50\xD0 ARM7
-reg32,reg32,imm32 \x24\x50\xD0 ARM7
-reg32,reg32,reg32 \x25\x10\xD0 ARM7
+reglo,memam3 \x65\x56\x0\0 THUMB,ARMv4T
+reg32,memam2 \x88\xF9\x10\x0\x0\0 THUMB32,ARMv6T2
+reg32,memam2 \x22\x10\xD0 ARM32,ARMv4
+reg32,reg32 \x23\x50\xD0 ARM32,ARMv4
+reg32,reg32,imm32 \x24\x50\xD0 ARM32,ARMv4
+reg32,reg32,reg32 \x25\x10\xD0 ARM32,ARMv4
[LDRSHcc]
-reg32,imm32 \x22\x50\xF0 ARM7
-reg32,reg32 \x23\x50\xF0 ARM7
-reg32,reg32,imm32 \x24\x50\xF0 ARM7
-reg32,reg32,reg32 \x25\x10\xF0 ARM7
+reglo,memam3 \x65\x5E\x0\1 THUMB,ARMv4T
+reg32,memam2 \x88\xF9\x30\x0\x0\0 THUMB32,ARMv6T2
+reg32,memam2 \x22\x10\xF0 ARM32,ARMv4
[LDRTcc]
+reg32,memam2 \x88\xF8\x50\xE\x0\0 THUMB32,ARMv6T2
+reg32,memam2 \x17\x04\x30 ARM32,ARMv4
-[LDFcc]
+[MCRcc]
+regf,immshifter,reg32,regf,regf \x1C\xE\x0\x1 ARM32,ARMv4
+regf,immshifter,reg32,regf,regf,immshifter \x1C\xE\x0\x1 ARM32,ARMv4
-[LFMcc]
-reg32,imm8,fpureg \xF0\x02\x01 FPA
+[MCR2cc]
+regf,immshifter,reg32,regf,regf \x1C\xFE\x0\x1 ARM32,ARMv5T
+regf,immshifter,reg32,regf,regf,immshifter \x1C\xFE\x0\x1 ARM32,ARMv5T
-[LGNcc]
+[MRCcc]
+regf,immshifter,reg32,regf,regf \x1C\xE\x10\x1 ARM32,ARMv4
+regf,immshifter,reg32,regf,regf,immshifter \x1C\xE\x10\x1 ARM32,ARMv4
-[LOGcc]
+[MRC2cc]
+regf,immshifter,reg32,regf,regf \x1C\xFE\x10\x1 ARM32,ARMv5T
+regf,immshifter,reg32,regf,regf,immshifter \x1C\xFE\x10\x1 ARM32,ARMv5T
+
+[MCRRcc]
+regf,immshifter,reg32,reg32,regf \x1D\xC\x40\x0 ARM32,ARMv5TE
+
+[MCRR2cc]
+regf,immshifter,reg32,reg32,regf \x1D\xFC\x40\x0 ARM32,ARMv6
+
+[MRRCcc]
+regf,immshifter,reg32,reg32,regf \x1D\xC\x50\x0 ARM32,ARMv5TE
-[MCR]
-; reg32,mem32 \320\301\1\x13\110 ARM7
+[MRRC2cc]
+regf,immshifter,reg32,reg32,regf \x1D\xFC\x50\x0 ARM32,ARMv6
[MLAcc]
-reg32,reg32,reg32,reg32 \x15\x00\x20\x90 ARM7
+reg32,reg32,reg32,reg32 \x80\xFB\x0\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x15\x00\x20\x9 ARM32,ARMv4
[MOVcc]
-; reg32,shifterop \x8\x0\0xd ARM7
-; reg32,immshifter \x8\x0\0xd ARM7
-; reg32,reg32,reg32 \x9\x1\xA0 ARM7
-; reg32,reg32,imm \xA\x1\xA0 ARM7
-; reg32,imm \xB\x3\xA0 ARM7
+reglo,reglo \x6B\x0\x0 THUMB,ARMv4T
+reg32,reg32 \x61\x46\x00 THUMB,ARMv4T
+
+reglo,immshifter \x6B\x20\x0 THUMB,ARMv4T
+
+reg32,immshifter \x80\xF0\x4F\x0\x0 THUMB32,WIDE,ARMv6T2
+
+reg32,reg32 \x80\xEA\x4F\x0\x0 THUMB32,WIDE,ARMv6T2
-[MRC]
-; reg32,reg32 \321\301\1\x13\110 ARM7
+reg32,shifterop \x8\x1\xA0 ARM32,ARMv4
+reg32,reg32,shifterop \xA\x1\xA0 ARM32,ARMv4
+reg32,immshifter \xB\x1\xA0 ARM32,ARMv4
[MRScc]
-reg32,reg32 \x10\x01\x0F ARM7
+reg32,regf \x96\xF3\xEF\x80\x0 THUMB32,ARMv6
+reg32,regf \x10\x01\x0F ARM32,ARMv4
[MSRcc]
-reg32,reg32 \x11\x01\x29\xF0 ARM7
-regf,reg32 \x12\x01\x28\xF0 ARM7
-regf,imm \x13\x03\x28\xF0 ARM7
+regf,reg32 \x96\xF3\x80\x80\x0 THUMB32,ARMv6
-[MNFcc]
-
-[MUFcc]
+regf,reg32 \x12\x01\x20\xF0 ARM32,ARMv4
+regf,immshifter \x13\x03\x20\xF0 ARM32,ARMv4
+regs,immshifter \x13\x03\x20\xF0 ARM32,ARMv4
[MULcc]
-reg32,reg32,reg32 \x14\x00\x00\x90 ARM7
+reglo,reglo \x64\x43\x40 THUMB,ARMv4T
+reglo,reglo,reglo \x64\x43\x40 THUMB,ARMv4T
+reg32,reg32 \x80\xFB\x00\xF0\x00 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x80\xFB\x00\xF0\x00 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x14\x00\x00\x90 ARM32,ARMv4
[MVFcc]
-fpureg,fpureg \xF2 FPA
-fpureg,immfpu \xF2 FPA
+fpureg,fpureg \xA1\1\x1 ARM32,FPA
+fpureg,immshifter \xA1\1\x1 ARM32,FPA
[MVNcc]
-; reg32,reg32 \x8\x0\0xf ARM7
-; reg32,reg32,reg32 \x9\x1\xE0 ARM7
-; reg32,reg32,imm \xA\x1\xE0 ARM7
-; reg32,imm \xB\x3\xE0 ARM7
+reglo,reglo \x6B\x43\xc0 THUMB,ARMv4T
-[NOP]
+reg32,immshifter \x80\xF0\x6F\x0\x0 THUMB32,ARMv6T2
+reg32,reg32 \x80\xEA\x6F\x0\x0 THUMB32,WIDE,ARMv6T2
-[ORRcc]
-reg32,reg32,reg32 \4\x1\x80 ARM7
-reg32,reg32,reg32,reg32 \5\x1\x80 ARM7
-reg32,reg32,reg32,imm \6\x1\x80 ARM7
-reg32,reg32,imm \7\x3\x80 ARM7
+reg32,reg32 \x8\x1\xE0 ARM32,ARMv4
+reg32,reg32,shifterop \xA\x1\xE0 ARM32,ARMv4
+reg32,immshifter \xB\x1\xE0 ARM32,ARMv4
-[RDFcc]
+[VMOVcc]
+vreg,vreg \x90\xEE\xB0\xA\x40 THUMB32,VFPv2
+vreg,vreg \x40\xE\xB0\xA\x40 ARM32,VFPv2
-[RFScc]
+reg32,vreg \x90\xEE\x10\xA\x10 THUMB32,VFPv2
+vreg,reg32 \x90\xEE\x00\xA\x10 THUMB32,VFPv2
+reg32,vreg \x40\xE\x10\xA\x10 ARM32,VFPv2
+vreg,reg32 \x40\xE\x00\xA\x10 ARM32,VFPv2
-[RFCcc]
+reg32,reg32,vreg,vreg \x90\xEC\x50\xA\x10 THUMB32,VFPv2
+vreg,vreg,reg32,reg32 \x90\xEC\x40\xA\x10 THUMB32,VFPv2
+reg32,reg32,vreg,vreg \x40\xC\x50\xA\x10 ARM32,VFPv2
+vreg,vreg,reg32,reg32 \x40\xC\x40\xA\x10 ARM32,VFPv2
-[RMFcc]
+reg32,reg32,vreg \x90\xEC\x50\xB\x10 THUMB32,VFPv2
+vreg,reg32,reg32 \x90\xEC\x40\xB\x10 THUMB32,VFPv2
+reg32,reg32,vreg \x40\xC\x50\xB\x10 ARM32,VFPv2
+vreg,reg32,reg32 \x40\xC\x40\xB\x10 ARM32,VFPv2
-[RPWcc]
+[NOP]
+void \x61\xBF\x0 THUMB,ARMv6T2
+void \x2F\x03\x20\xF0\x0 ARM32,ARMv6K
+; Before ARMv6K use mov r0,r0
+void \x2F\xE1\xA0\x0\x0 ARM32,ARMv4
+
+[ORNcc]
+reg32,immshifter \x80\xF0\x60\x0\x0 THUMB32,ARMv6T2
+reg32,reg32 \x80\xEA\x60\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,shifterop \x80\xEA\x60\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,immshifter \x80\xF0\x60\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x80\xEA\x60\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\x60\x0\x0 THUMB32,ARMv6T2
-[RSBcc]
-reg32,reg32,reg32 \4\x0\x60 ARM7
-reg32,reg32,reg32,reg32 \5\x0\x60 ARM7
-reg32,reg32,reg32,imm \6\x0\x60 ARM7
-reg32,reg32,imm \7\x2\x60 ARM7
+[ORRcc]
+reglo,reglo \x6B\x43\x00 THUMB,ARMv4T
-[RSCcc]
-reg32,reg32,reg32 \4\x0\xE0 ARM7
-reg32,reg32,reg32,reg32 \5\x0\xE0 ARM7
-reg32,reg32,reg32,imm \6\x0\xE0 ARM7
-reg32,reg32,imm \7\x2\xE0 ARM7
+reg32,immshifter \x80\xF0\x40\x0\x0 THUMB32,ARMv6T2
+reg32,reg32 \x80\xEA\x40\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x80\xEA\x40\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter \x80\xF0\x40\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x80\xEA\x40\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\x40\x0\x0 THUMB32,WIDE,ARMv6T2
-[RSFcc]
+reg32,reg32,reg32 \4\x1\x80 ARM32,ARMv4
+reg32,reg32,reg32,reg32 \5\x1\x80 ARM32,ARMv4
+reg32,reg32,reg32,shifterop \6\x1\x80 ARM32,ARMv4
+reg32,reg32,immshifter \7\x3\x80 ARM32,ARMv4
-[RNDcc]
+[RSBcc]
+reglo,reglo,immzero \x6B\x42\x40 THUMB,ARMv4T
-[POLcc]
+reg32,immshifter \x80\xF1\xC0\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32 \x80\xEB\xC0\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,shifterop \x80\xEB\xC0\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,immshifter \x80\xF1\xC0\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32 \x80\xEB\xC0\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEB\xC0\x0\x0 THUMB32,ARMv6T2
+
+reg32,reg32,reg32 \6\x0\x60 ARM32,ARMv4
+reg32,reg32,reg32,shifterop \6\x0\x60 ARM32,ARMv4
+reg32,reg32,immshifter \7\x0\x60 ARM32,ARMv4
+
+[RSCcc]
+reg32,reg32,reg32 \4\x0\xE0 ARM32,ARMv4
+reg32,reg32,reg32,reg32 \5\x0\xE0 ARM32,ARMv4
+reg32,reg32,reg32,shifterop \6\x0\xE0 ARM32,ARMv4
+reg32,reg32,immshifter \7\x2\xE0 ARM32,ARMv4
[SBCcc]
-reg32,reg32,reg32 \4\x0\xC0 ARM7
-reg32,reg32,reg32,reg32 \5\x0\xC0 ARM7
-reg32,reg32,reg32,imm \6\x0\xC0 ARM7
-reg32,reg32,imm \7\x2\xC0 ARM7
+reglo,reglo \x6B\x41\x80 THUMB,ARMv4T
+
+reg32,immshifter \x80\xF1\x60\x0\x0 THUMB32,ARMv6T2
+reg32,reg32 \x80\xEB\x60\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x80\xEB\x60\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter \x80\xF1\x60\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x80\xEB\x60\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEB\x60\x0\x0 THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,reg32 \4\x0\xC0 ARM32,ARMv4
+reg32,reg32,reg32,reg32 \5\x0\xC0 ARM32,ARMv4
+reg32,reg32,reg32,imm \6\x0\xC0 ARM32,ARMv4
+reg32,reg32,reg32,shifterop \6\x0\xC0 ARM32,ARMv4
+reg32,reg32,immshifter \7\x2\xC0 ARM32,ARMv4
[SFMcc]
-reg32,imm8,fpureg \xF0\x02\x00 FPA
+fpureg,imm32,memam2 \xA0\xC\x00\x2\x0 ARM32,FPA
+fpureg,immshifter,memam2 \xA0\xC\x00\x2\x0 ARM32,FPA
[SINcc]
+fpureg,fpureg \xA1\1\x11 ARM32,FPA
+fpureg,immshifter \xA1\1\x11 ARM32,FPA
[SMLALcc]
-reg32,reg32,reg32,reg32 \x16\x00\xE0\x90 ARM7
+reg32,reg32,reg32,reg32 \x85\xFB\xC0\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x16\x00\xE0\x9 ARM32,ARMv4
[SMULLcc]
-reg32,reg32,reg32,reg32 \x16\x00\xC0\x90 ARM7
-
-[SQTcc]
+reg32,reg32,reg32,reg32 \x85\xFB\x80\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x16\x00\xC0\x9 ARM32,ARMv4
-[SUFcc]
+[STMcc]
+memam4,reglist \x69\xC0 THUMB,ARMv4T
+reglo,reglist \x69\xC0 THUMB,ARMv4T
-[STFcc]
+memam4,reglist \x8C\xE8\x00\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reglist \x8C\xE8\x00\x0\x0 THUMB32,WIDE,ARMv6T2
-[STMcc]
-memam4,reglist \x26\x80 ARM7
+memam4,reglist \x26\x80 ARM32,ARMv4
+reg32,reglist \x26\x80 ARM32,ARMv4
[STRcc]
-reg32,memam2 \x17\x04\x00 ARM7
-; reg32,imm32 \x17\x05\x00 ARM7
-; reg32,reg32 \x18\x04\x00 ARM7
-; reg32,reg32,imm32 \x19\x04\x00 ARM7
-; reg32,reg32,reg32 \x20\x06\x00 ARM7
-; reg32,reg32,reg32,imm32 \x21\x06\x00 ARM7
+reglo,memam3 \x65\x50\x0\2 THUMB,ARMv4T
+reglo,memam4 \x66\x60\x0\2 THUMB,ARMv4T
+reglo,memam5 \x67\x90\x0\2 THUMB,ARMv4T
+reg32,memam2 \x88\xF8\x40\x0\x0\0 THUMB32,WIDE,ARMv6T2
+reg32,memam2 \x17\x04\x00 ARM32,ARMv4
[STRBcc]
-reg32,memam2 \x17\x06\x00 ARM7
+reglo,memam3 \x65\x54\x0\0 THUMB,ARMv4T
+reglo,memam4 \x66\x70\x0\0 THUMB,ARMv4T
+reg32,memam2 \x88\xF8\x00\x0\x0\0 THUMB32,WIDE,ARMv6T2
+reg32,memam2 \x17\x04\x40 ARM32,ARMv4
[STRBTcc]
+reg32,memam2 \x88\xF8\x00\xE\x0\0 THUMB32,ARMv6T2
+reg32,memam2 \x17\x04\x60 ARM32,ARMv4
+reg32,immshifter \x17\x04\x60 ARM32,ARMv4
-; A dummy since it is parsed as STR{cond}H
[STRHcc]
-reg32,imm32 \x22\x40\xB0 ARM7
-reg32,reg32 \x23\x40\xB0 ARM7
-reg32,reg32,imm32 \x24\x40\xB0 ARM7
-reg32,reg32,reg32 \x25\x00\xB0 ARM7
+reglo,memam3 \x65\x52\x0\1 THUMB,ARMv4T
+reglo,memam4 \x66\x80\x0\1 THUMB,ARMv4T
+reg32,memam2 \x88\xF8\x20\x0\x0\0 THUMB32,WIDE,ARMv6T2
+reg32,memam2 \x22\x00\xB0 ARM32,ARMv4
[STRTcc]
+reg32,memam2 \x88\xF8\x40\xE\x0\0 THUMB32,ARMv6T2
+reg32,memam2 \x17\x04\x20 ARM32,ARMv4
[SUBcc]
-reg32,reg32,shifterop \4\x0\x40 ARM7
-reg32,reg32,immshifter \4\x0\x40 ARM7
-reg32,reg32,reg32 \4\x0\x40 ARM7
-; reg32,reg32,reg32,reg32 \5\x0\x40 ARM7
-; reg32,reg32,reg32,imm \6\x0\x40 ARM7
-; reg32,reg32,imm \7\x2\x40 ARM7
+regsp,immshifter \x64\xB0\x80 THUMB,ARMv4T
+regsp,regsp,immshifter \x64\xB0\x80 THUMB,ARMv4T
+reglo,reglo \x60\x1A\x0 THUMB,ARMv4T
+reglo,reglo,reglo \x60\x1A\x0 THUMB,ARMv4T
+
+reglo,immshifter \x60\x1E\x0 THUMB,ARMv4T
+reglo,reglo,immshifter \x60\x1E\x0 THUMB,ARMv4T
+reglo,imm8 \x6B\x38\x0 THUMB,ARMv4T
+reglo,immshifter \x6B\x38\x0 THUMB,ARMv4T
+
+reg32,immshifter \x80\xF1\xA0\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32 \x80\xEB\xA0\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x80\xEB\xA0\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter \x80\xF1\xA0\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32 \x80\xEB\xA0\x0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEB\xA0\x0\x0 THUMB32,WIDE,ARMv6T2
+
+reg32,reg32,shifterop \x4\x0\x40 ARM32,ARMv4
+reg32,reg32,immshifter \x4\x0\x40 ARM32,ARMv4
+reg32,reg32,reg32 \x4\x0\x40 ARM32,ARMv4
+reg32,reg32,reg32,shifterop \x6\x0\x40 ARM32,ARMv4
[SWIcc]
-imm \2\x0F ARM7
+; Old alias for SVC
[SWPcc]
-reg32,reg32,reg32 \x27\x01\x90 ARM7
+reg32,reg32,memam2 \x27\x10\x09 ARM32,ARMv4
[SWPBcc]
-reg32,reg32,reg32 \x27\x01\x90 ARM7
-
-[TANcc]
+reg32,reg32,memam2 \x27\x14\x09 ARM32,ARMv4
[TEQcc]
-reg32,reg32 \xC\x1\x20 ARM7
-reg32,reg32,reg32 \xD\x1\x20 ARM7
-reg32,reg32,imm \xE\x1\x20 ARM7
-reg32,imm \xF\x3\x20 ARM7
+reg32,immshifter \x80\xF0\x90\x0F\x00 THUMB32,ARMv6T2
+reg32,reg32 \x80\xEA\x90\x0F\x00 THUMB32,ARMv6T2
+reg32,reg32,shifterop \x80\xEA\x90\x0F\x00 THUMB32,ARMv6T2
+
+reg32,reg32 \xC\x1\x20 ARM32,ARMv4
+reg32,reg32,reg32 \xD\x1\x20 ARM32,ARMv4
+reg32,reg32,shifterop \xE\x1\x20 ARM32,ARMv4
+reg32,immshifter \xF\x3\x20 ARM32,ARMv4
[TSTcc]
-reg32,reg32 \xC\x1\x00 ARM7
-reg32,reg32,reg32 \xD\x1\x00 ARM7
-reg32,reg32,imm \xE\x1\x00 ARM7
-reg32,imm \xF\x3\x00 ARM7
+reglo,reglo \x6B\x42\x00 THUMB,ARMv4T
+
+reg32,immshifter \x80\xF0\x10\x0F\x00 THUMB32,ARMv6T2
+reg32,reg32 \x80\xEA\x10\x0F\x00 THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x80\xEA\x10\x0F\x00 THUMB32,WIDE,ARMv6T2
+
+reg32,reg32 \xC\x1\x00 ARM32,ARMv4
+reg32,reg32,reg32 \xD\x1\x00 ARM32,ARMv4
+reg32,reg32,shifterop \xE\x1\x00 ARM32,ARMv4
+reg32,immshifter \xF\x3\x00 ARM32,ARMv4
[UMLALcc]
-reg32,reg32,reg32,reg32 \x16\x00\xA0\x90 ARM7
+reg32,reg32,reg32,reg32 \x85\xFB\xE0\x0\x00 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x16\x00\xA0\x9 ARM32,ARMv4
[UMULLcc]
-reg32,reg32,reg32,reg32 \x16\x00\x80\x90 ARM7
+reg32,reg32,reg32,reg32 \x85\xFB\xA0\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x16\x00\x80\x9 ARM32,ARMv4
[WFScc]
+reg32 \xA2\xE\x2 ARM32,FPA
; EDSP instructions
[LDRDcc]
-
-[MCRRcc]
-
-[MRRCcc]
+reg32,reg32,memam2 \x89\xE8\x50\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,memam2 \x19\x0\x0\x0\xD0 ARM32,ARMv4
[PLD]
+memam2 \x87\xF8\x10\xF0\x0 THUMB32,ARMv6T2
+memam2 \x25\xF5\x50\xF0\x0 ARM32,ARMv5TE
+
+[PLDW]
+memam2 \x87\xF8\x30\xF0\x0 THUMB32,ARMv7
+memam2 \x25\xF5\x10\xF0\x0 ARM32,ARMv7
[QADDcc]
+reg32,reg32,reg32 \x82\xFA\x80\xF0\x80 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x1A\x01\x00\x05 ARM32,ARMv5TE
[QDADDcc]
+reg32,reg32,reg32 \x82\xFA\x80\xF0\x90 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x1A\x01\x40\x05 ARM32,ARMv5TE
[QDSUBcc]
+reg32,reg32,reg32 \x82\xFA\x80\xF0\xB0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x1A\x01\x60\x05 ARM32,ARMv5TE
[QSUBcc]
+reg32,reg32,reg32 \x82\xFA\x80\xF0\xA0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x1A\x01\x20\x05 ARM32,ARMv5TE
[SMLABBcc]
+reg32,reg32,reg32,reg32 \x15\x01\x00\x8 ARM32,ARMv5TE
[SMLABTcc]
+reg32,reg32,reg32,reg32 \x15\x01\x00\xC ARM32,ARMv5TE
[SMLATBcc]
+reg32,reg32,reg32,reg32 \x15\x01\x00\xA ARM32,ARMv5TE
[SMLATTcc]
+reg32,reg32,reg32,reg32 \x15\x01\x00\xE ARM32,ARMv5TE
[SMLALBBcc]
+reg32,reg32,reg32,reg32 \x16\x01\x40\x8 ARM32,ARMv5TE
[SMLALBTcc]
+reg32,reg32,reg32,reg32 \x16\x01\x40\xC ARM32,ARMv5TE
[SMLALTBcc]
+reg32,reg32,reg32,reg32 \x16\x01\x40\xA ARM32,ARMv5TE
[SMLALTTcc]
+reg32,reg32,reg32,reg32 \x16\x01\x40\xE ARM32,ARMv5TE
[SMLAWBcc]
+reg32,reg32,reg32,reg32 \x80\xFB\x30\x0\x00 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x15\x1\x20\x8 ARM32,ARMv5TE
[SMLAWTcc]
+reg32,reg32,reg32,reg32 \x80\xFB\x30\x0\x10 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x15\x1\x20\xC ARM32,ARMv5TE
+
+[VLDMcc]
+memam4,reglist \x94\xEC\x10\xA THUMB32,VFPv2
+reg32,reglist \x94\xEC\x10\xA THUMB32,VFPv2
+memam4,reglist \x44\xC\x10\xA ARM32,VFPv2
+reg32,reglist \x44\xC\x10\xA ARM32,VFPv2
+
+[VSTMcc]
+memam4,reglist \x94\xEC\x00\xA THUMB32,VFPv2
+reg32,reglist \x94\xEC\x00\xA THUMB32,VFPv2
+memam4,reglist \x44\xC\x00\xA ARM32,VFPv2
+reg32,reglist \x44\xC\x00\xA ARM32,VFPv2
+
+[VPOP]
+reglist \x94\xEC\xBD\xA THUMB32,VFPv2
+reglist \x44\xC\xBD\xA ARM32,VFPv2
+
+[VPUSH]
+reglist \x94\xED\x2D\xA THUMB32,VFPv2
+reglist \x44\xD\x2D\xA ARM32,VFPv2
+
+[VLDRcc]
+vreg,memam2 \x95\xED\x10\xA THUMB32,VFPv2
+vreg,memam2 \x45\xD\x10\xA ARM32,VFPv2
+
+[VSTRcc]
+vreg,memam2 \x95\xED\x0\xA THUMB32,VFPv2
+vreg,memam2 \x45\xD\x0\xA ARM32,VFPv2
[SMULBBcc]
+reg32,reg32,reg32 \x15\x01\x60\x8\x0 ARM32,ARMv5TE
[SMULBTcc]
+reg32,reg32,reg32 \x15\x01\x60\xC\x0 ARM32,ARMv5TE
[SMULTBcc]
+reg32,reg32,reg32 \x15\x01\x60\xA\x0 ARM32,ARMv5TE
[SMULTTcc]
+reg32,reg32,reg32 \x15\x01\x60\xE\x0 ARM32,ARMv5TE
[SMULWBcc]
+reg32,reg32,reg32 \x14\x1\x20\xA0 ARM32,ARMv5TE
[SMULWTcc]
+reg32,reg32,reg32 \x14\x1\x20\xE0 ARM32,ARMv5TE
[STRDcc]
+reg32,reg32,memam2 \x89\xE8\x40\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,memam2 \x19\x0\x0\x0\xF0 ARM32,ARMv4
-;
-; vfp instructions
-;
-[FABSDcc]
+[LDRHTcc]
+reg32,memam2 \x88\xF8\x30\xE\x0\0 THUMB32,ARMv6T2
+reg32,memam2 \x19\x0\x30\x0\xB0 ARM32,ARMv4
-[FABSScc]
+[STRHTcc]
+reg32,memam2 \x88\xF8\x20\xE\x0\0 THUMB32,ARMv6T2
-[FADDDcc]
+reg32,memam2 \x88\xF8\x20\xE\x0\0 THUMB32,ARMv6T2
+reg32,memam2 \x1E\x0\x20\x0\xB0 ARM32,ARMv4
-[FADDScc]
+[LDRSBTcc]
+reg32,memam2 \x88\xF9\x10\xE\x0\0 THUMB32,ARMv6T2
+reg32,memam2 \x1E\x0\x30\x0\xD0 ARM32,ARMv4
-[FCMPDcc]
+[LDRSHTcc]
+reg32,memam2 \x88\xF9\x30\xE\x0\0 THUMB32,ARMv6T2
+reg32,memam2 \x1E\x0\x30\x0\xF0 ARM32,ARMv4
-[FCMPEDcc]
+[FSTDcc]
+vreg,memam2 \x95\xED\x0\xA THUMB32,VFPv2
+vreg,memam2 \x45\xD\x0\xA ARM32,VFPv2
-[FCMPEScc]
+[FSTMcc]
+memam4,reglist \x94\xEC\x00\xA THUMB32,VFPv2
+reg32,reglist \x94\xEC\x00\xA THUMB32,VFPv2
+memam4,reglist \x44\xC\x00\xA ARM32,VFPv2
+reg32,reglist \x44\xC\x00\xA ARM32,VFPv2
-[FCMPEZDcc]
+[FSTScc]
+vreg,memam2 \x95\xED\x0\xA THUMB32,VFPv2
+vreg,memam2 \x45\xD\x0\xA ARM32,VFPv2
-[FCMPEZScc]
+; ARMv6
-[FCMPScc]
+[BFCcc]
+reg32,immshifter,immshifter \x84\xF3\x6F\x0\x0 THUMB32,ARMv6T2
+reg32,immshifter,imm32 \x84\xF3\x6F\x0\x0 THUMB32,ARMv6T2
-[FCMPZDcc]
+reg32,immshifter,immshifter \x2D\x7\xC0\x0\x1F ARM32,ARMv4
+reg32,immshifter,imm32 \x2D\x7\xC0\x0\x1F ARM32,ARMv4
-[FCMPZScc]
+[BFIcc]
+reg32,reg32,immshifter,immshifter \x84\xF3\x60\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,immshifter,imm32 \x84\xF3\x60\x0\x0 THUMB32,ARMv6T2
-[FCPYDcc]
+reg32,reg32,immshifter,immshifter \x2D\x7\xC0\x0\x10 ARM32,ARMv4
+reg32,reg32,immshifter,imm32 \x2D\x7\xC0\x0\x10 ARM32,ARMv4
-[FCPYScc]
+[CLREX]
+void \x80\xF3\xBF\x8F\x2F THUMB32,ARMv7
+void \x2F\xF5\x7F\xF0\x1F ARM32,ARMv6K
-[FCVTDScc]
+[LDREXcc]
+reg32,memam6 \x8A\xE8\x50\x0F\x00 THUMB32,ARMv6T2
+reg32,memam6 \x18\x01\x90\x0F\x9F ARM32,ARMv4
-[FCVTSDcc]
+[LDREXBcc]
+reg32,memam6 \x8A\xE8\xD0\x0F\x4F THUMB32,ARMv7
+reg32,memam6 \x18\x01\xD0\x0F\x9F ARM32,ARMv4
-[FDIVDcc]
+[LDREXDcc]
+reg32,reg32,memam6 \x8A\xE8\xD0\x00\x7F THUMB32,ARMv7
+reg32,reg32,memam6 \x18\x01\xB0\x0F\x9F ARM32,ARMv4
-[FDIVScc]
+[LDREXHcc]
+reg32,memam6 \x8A\xE8\xD0\x0F\x5F THUMB32,ARMv7
+reg32,memam6 \x18\x01\xF0\x0F\x9F ARM32,ARMv4
-[FLDDcc]
+[STREXcc]
+reg32,reg32,memam6 \x8B\xE8\x40\x00\x00 THUMB32,ARMv6T2
+reg32,reg32,memam6 \x18\x01\x80\x0F\x90 ARM32,ARMv4
-[FLDMcc]
+[STREXBcc]
+reg32,reg32,memam6 \x8B\xE8\xC0\x0F\x40 THUMB32,ARMv7
+reg32,reg32,memam6 \x18\x01\xC0\x0F\x90 ARM32,ARMv4
-[FLDScc]
+[STREXDcc]
+reg32,reg32,reg32,memam6 \x8B\xE8\xC0\x00\x70 THUMB32,ARMv7
+reg32,reg32,reg32,memam6 \x18\x01\xA0\x0F\x90 ARM32,ARMv4
-[FMACDcc]
+[STREXHcc]
+reg32,reg32,memam6 \x8B\xE8\xC0\x0F\x50 THUMB32,ARMv7
+reg32,reg32,memam6 \x18\x01\xE0\x0F\x90 ARM32,ARMv4
-[FMACScc]
+[MLScc]
+reg32,reg32,reg32,reg32 \x80\xFB\x0\x0\x10 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x15\x00\x60\x9 ARM32,ARMv6T2
-[FMDHRcc]
+[PKHBTcc]
+reg32,reg32,reg32 \x80\xEA\xC0\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\xC0\x0\x0 THUMB32,ARMv6T2
-[FMDLRcc]
+reg32,reg32,reg32 \x16\x6\x80\x1 ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x6\x80\x1 ARM32,ARMv6
-[FMRDHcc]
+[PKHTBcc]
+reg32,reg32,reg32 \x80\xEA\xC0\x0\x10 THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x80\xEA\xC0\x0\x10 THUMB32,ARMv6T2
-[FMRDLcc]
+reg32,reg32,reg32 \x16\x6\x80\x1 ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x6\x80\x5 ARM32,ARMv6
-[FMRScc]
+[PLI]
+memam2 \x87\xF9\x10\xF0\x0 THUMB32,ARMv7
+memam2 \x25\xF4\x50\xF0\x0 ARM32,ARMv7
-[FMRXcc]
+[QADD16cc]
+reg32,reg32,reg32 \x80\xFA\x90\xF0\x10 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x20\xF1 ARM32,ARMv6
+[QADD8cc]
+reg32,reg32,reg32 \x80\xFA\x80\xF0\x10 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x20\xF9 ARM32,ARMv6
+[QASXcc]
+reg32,reg32,reg32 \x80\xFA\xA0\xF0\x10 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x20\xF3 ARM32,ARMv6
+[QSAXcc]
+reg32,reg32,reg32 \x80\xFA\xE0\xF0\x10 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x20\xF5 ARM32,ARMv6
+[QSUB16cc]
+reg32,reg32,reg32 \x80\xFA\xD0\xF0\x10 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x20\xF7 ARM32,ARMv6
+[QSUB8cc]
+reg32,reg32,reg32 \x80\xFA\xC0\xF0\x10 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x20\xFF ARM32,ARMv6
-[FMSCDcc]
+[RBITcc]
+reg32,reg32 \x80\xFA\x90\xF0\xA0 THUMB32,ARMv6T2
+reg32,reg32 \x32\x6\xFF\xF\x30 ARM32,ARMv6T2
-[FMSCScc]
+[REVcc]
+reglo,reglo \x61\xBA\x00 THUMB,ARMv6
+reg32,reg32 \x80\xFA\x90\xF0\x80 THUMB32,WIDE,ARMv6T2
+reg32,reg32 \x32\x6\xBF\xF\x30 ARM32,ARMv6
-[FMSRcc]
+[REV16cc]
+reglo,reglo \x61\xBA\x40 THUMB,ARMv6
+reg32,reg32 \x80\xFA\x90\xF0\x90 THUMB32,WIDE,ARMv6T2
+reg32,reg32 \x32\x6\xBF\xF\xB0 ARM32,ARMv6
-[FMSTATcc]
+[REVSHcc]
+reglo,reglo \x61\xBA\xC0 THUMB,ARMv6
+reg32,reg32 \x80\xFA\x90\xF0\xB0 THUMB32,WIDE,ARMv6T2
+reg32,reg32 \x32\x6\xFF\xF\xB0 ARM32,ARMv6
-[FMULDcc]
+[SADD16cc]
+reg32,reg32,reg32 \x80\xFA\90\xF0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x10\xF1 ARM32,ARMv6
-[FMULScc]
+[SADD8cc]
+reg32,reg32,reg32 \x80\xFA\80\xF0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x10\xF9 ARM32,ARMv6
-[FMXRcc]
+[SASXcc]
+reg32,reg32,reg32 \x80\xFA\A0\xF0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x10\xF3 ARM32,ARMv6
-[FNEGDcc]
+[SBFXcc]
+reg32,reg32,immshifter,immshifter \x84\xF3\x40\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,immshifter,immshifter \x2D\x7\xA0\x0\x50 ARM32,ARMv6T2
-[FNEGScc]
+[SELcc]
+reg32,reg32,reg32 \x80\xFA\xA0\xF0\x80 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x80\xFB ARM32,ARMv6
-[FNMACDcc]
+[SETEND]
+immshifter \x2B\xF1\x01\x0\x0 ARM32,ARMv6
-[FNMACScc]
+[SEVcc]
+void \x64\xBF\x40 THUMB,ARMv7
+void \x2F\x3\x20\xF0\x4 ARM32,ARMv6K
-[FNMSCDcc]
+[ASRcc]
+reglo,immshifter \x60\x1\x0 THUMB,ARMv4T
+reglo,reglo,immshifter \x60\x1\x0 THUMB,ARMv4T
+reglo,reglo \x6B\x41\x0 THUMB,ARMv4T
-[FNMSCScc]
+reg32,immshifter \x82\xEA\x4F\x0\x20 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter \x82\xEA\x4F\x0\x20 THUMB32,WIDE,ARMv6T2
+reg32,reg32 \x80\xFA\x40\xF0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32 \x80\xFA\x40\xF0\x0 THUMB32,WIDE,ARMv6T2
-[FNMULDcc]
+reg32,reg32,reg32 \x30\x1\xA0\x0\x50 ARM32,ARMv4
+reg32,reg32,immshifter \x30\x1\xA0\x0\x40 ARM32,ARMv4
-[FNMULScc]
+[LSRcc]
+reglo,immshifter \x60\x8\x0 THUMB,ARMv4T
+reglo,reglo,immshifter \x60\x8\x0 THUMB,ARMv4T
+reglo,reglo \x6B\x40\xC0 THUMB,ARMv4T
-[FSITODcc]
+reg32,immshifter \x82\xEA\x4F\x0\x10 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter \x82\xEA\x4F\x0\x10 THUMB32,WIDE,ARMv6T2
+reg32,reg32 \x80\xFA\x20\xF0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32 \x80\xFA\x20\xF0\x0 THUMB32,WIDE,ARMv6T2
-[FSITOScc]
+reg32,reg32,reg32 \x30\x1\xA0\x0\x30 ARM32,ARMv4
+reg32,reg32,immshifter \x30\x1\xA0\x0\x20 ARM32,ARMv4
-[FSQRTDcc]
+[LSLcc]
+reglo,immshifter \x60\x0\x0 THUMB,ARMv4T
+reglo,reglo,immshifter \x60\x0\x0 THUMB,ARMv4T
+reglo,reglo \x6B\x40\x80 THUMB,ARMv4T
-[FSQRTScc]
+reg32,immshifter \x82\xEA\x4F\x0\x00 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter \x82\xEA\x4F\x0\x00 THUMB32,WIDE,ARMv6T2
+reg32,reg32 \x80\xFA\x60\xF0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32 \x80\xFA\x60\xF0\x0 THUMB32,WIDE,ARMv6T2
-[FSTDcc]
+reg32,reg32,reg32 \x30\x1\xA0\x0\x10 ARM32,ARMv4
+reg32,reg32,immshifter \x30\x1\xA0\x0\x00 ARM32,ARMv4
-[FSTMcc]
+[RORcc]
+reglo,reglo \x6B\x41\xC0 THUMB,ARMv4T
-[FSTScc]
+reg32,immshifter \x82\xEA\x4F\x0\x30 THUMB32,WIDE,ARMv6T2
+reg32,reg32,immshifter \x82\xEA\x4F\x0\x30 THUMB32,WIDE,ARMv6T2
+reg32,reg32 \x80\xFA\x60\xF0\x0 THUMB32,WIDE,ARMv6T2
+reg32,reg32,reg32 \x80\xFA\x60\xF0\x0 THUMB32,WIDE,ARMv6T2
-[FSUBDcc]
+reg32,reg32,reg32 \x30\x1\xA0\x0\x70 ARM32,ARMv4
+reg32,reg32,immshifter \x30\x1\xA0\x0\x60 ARM32,ARMv4
-[FSUBScc]
+[RRXcc]
+reg32,reg32 \x80\xEA\x4F\x00\x30 THUMB32,ARMv6T2
+reg32,reg32 \x30\x1\xA0\x0\x60 ARM32,ARMv4
-[FTOSIDcc]
+[UMAALcc]
+reg32,reg32,reg32,reg32 \x85\xFB\xE0\x0\x60 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x16\x0\x40\x9 ARM32,ARMv6
-[FTOSIScc]
+[SHADD16cc]
+reg32,reg32,reg32 \x80\xFA\x90\xF0\x20 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x30\xF1 ARM32,ARMv6
-[FTOUIDcc]
+[SHADD8cc]
+reg32,reg32,reg32 \x80\xFA\x80\xF0\x20 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x30\xF9 ARM32,ARMv6
-[FTOUIScc]
+[SHASXcc]
+reg32,reg32,reg32 \x80\xFA\xA0\xF0\x20 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x30\xF3 ARM32,ARMv6
-[FUITODcc]
+[SHSAXcc]
+reg32,reg32,reg32 \x80\xFA\xE0\xF0\x20 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x30\xF5 ARM32,ARMv6
-[FUITOScc]
+[SHSUB16cc]
+reg32,reg32,reg32 \x80\xFA\xD0\xF0\x20 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x30\xF7 ARM32,ARMv6
-[FMDRRcc]
+[SHSUB8cc]
+reg32,reg32,reg32 \x80\xFA\xC0\xF0\x20 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x30\xFF ARM32,ARMv6
-[FMRRDcc]
+[SMLADcc]
+reg32,reg32,reg32,reg32 \x80\xFB\x20\x0\x00 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x15\x7\x00\x1 ARM32,ARMv6
-; ARMv6
+[SMLALDcc]
+reg32,reg32,reg32,reg32 \x85\xFB\xC0\x0\xC0 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x16\x7\x40\x1 ARM32,ARMv4
-[BFCcc]
+[SMLSDcc]
+reg32,reg32,reg32,reg32 \x80\xFB\x40\x0\x00 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x15\x7\x00\x5 ARM32,ARMv6
-[BFIcc]
+[SMLSLDcc]
+reg32,reg32,reg32,reg32 \x85\xFB\xD0\x0\xC0 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x16\x7\x40\x5 ARM32,ARMv6
-[CLREX]
+[SMMLAcc]
+reg32,reg32,reg32,reg32 \x80\xFB\x50\x0\x00 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x15\x7\x50\x1 ARM32,ARMv6
-[LDREXcc]
-[LDREXBcc]
-[LDREXDcc]
-[LDREXHcc]
+[SMMLScc]
+reg32,reg32,reg32,reg32 \x80\xFB\x60\x0\x00 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x15\x7\x50\xD ARM32,ARMv6
-[MLScc]
+[SMMULcc]
+reg32,reg32,reg32 \x80\xFB\x50\xF0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x15\x7\x50\x1\xF ARM32,ARMv6
-[PKHcc]
+[SMUADcc]
+reg32,reg32,reg32 \x80\xFB\x20\xF0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x15\x7\x00\x1\xF ARM32,ARMv6
-[PLI]
+[SMUSDcc]
+reg32,reg32,reg32 \x80\xFB\x40\xF0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x15\x7\x00\x5\xF ARM32,ARMv6
-[QADD16cc]
-[QADD8cc]
-[QASXcc]
-[QSAXcc]
-[QSUB16cc]
-[QSUB8cc]
+[SRScc]
-[RBITcc]
+[SSATcc]
+reg32,immshifter,reg32 \x83\xF3\x00\x0\x0 THUMB32,ARMv6T2
+reg32,immshifter,reg32,shifterop \x83\xF3\x00\x0\x0 THUMB32,ARMv6T2
-[REVcc]
-[REV16cc]
-[REVSHcc]
+reg32,immshifter,reg32 \x2A\x6\xA0\x0\x10 ARM32,ARMv6
+reg32,immshifter,reg32,shifterop \x2A\x6\xA0\x0\x10 ARM32,ARMv6
-[SADD16cc]
-[SADD8cc]
-[SASXcc]
+[SSAT16cc]
+reg32,immshifter,reg32 \x83\xF3\x20\x0\x0 THUMB32,ARMv6T2
+reg32,immshifter,reg32 \x2A\x6\xA0\xF\x30 ARM32,ARMv6
-[SBFXcc]
+[SSAXcc]
+reg32,reg32,reg32 \x80\xFA\xE0\xF0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x10\xF5 ARM32,ARMv6
-[SELcc]
+[SSUB16cc]
+reg32,reg32,reg32 \x80\xFA\xD0\xF0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x10\xF7 ARM32,ARMv6
-[SETEND]
+[SSUB8cc]
+reg32,reg32,reg32 \x80\xFA\xC0\xF0\x0 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x10\xFF ARM32,ARMv6
-[SEVcc]
+[SXTABcc]
+reg32,reg32,reg32 \x86\xFA\x40\xF0\x80 THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x40\xF0\x80 THUMB32,ARMv6T2
-[ASRcc]
+reg32,reg32,reg32 \x16\x06\xA0\x07 ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x06\xA0\x07 ARM32,ARMv6
-[LSRcc]
+[SXTAB16cc]
+reg32,reg32,reg32 \x86\xFA\x20\xF0\x80 THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x20\xF0\x80 THUMB32,ARMv6T2
-[LSLcc]
+reg32,reg32,reg32 \x16\x06\x80\x07 ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x06\x80\x07 ARM32,ARMv6
-[RORcc]
+[SXTAHcc]
+reg32,reg32,reg32 \x86\xFA\x00\xF0\x80 THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x00\xF0\x80 THUMB32,ARMv6T2
-[SHADD16cc]
-[SHADD8cc]
-[SHASXcc]
-[SHSAXcc]
-[SHSUB16cc]
-[SHSUB8cc]
+reg32,reg32,reg32 \x16\x06\xB0\x07 ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x06\xB0\x07 ARM32,ARMv6
-[SMLADcc]
-[SMLALDcc]
-[SMLSDcc]
-[SMLSLDcc]
-[SMMLAcc]
-[SMMLScc]
-[SMMULcc]
-[SMUADcc]
-[SMUSDcc]
+[UBFXcc]
+reg32,reg32,immshifter,immshifter \x84\xF3\xC0\x0\x0 THUMB32,ARMv6T2
+reg32,reg32,immshifter,immshifter \x2D\x7\xE0\x0\x50 ARM32,ARMv4
-[SRScc]
+[UXTABcc]
+reg32,reg32,reg32 \x86\xFA\x50\xF0\x80 THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x50\xF0\x80 THUMB32,ARMv6T2
-[SSATcc]
-[SSAT16cc]
-[SSAXcc]
+reg32,reg32,reg32 \x16\x6\xE0\x7 ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x6\xE0\x7 ARM32,ARMv6
-[SSUB16cc]
-[SSUB8cc]
+[UXTAB16cc]
+reg32,reg32,reg32 \x86\xFA\x30\xF0\x80 THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x30\xF0\x80 THUMB32,ARMv6T2
-[STREXcc]
-[STREXBcc]
-[STREXDcc]
-[STREXHcc]
+reg32,reg32,reg32 \x86\xFA\x40\xF0\x80 THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x40\xF0\x80 THUMB32,ARMv6T2
+
+reg32,reg32,reg32 \x16\x6\xC0\x7 ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x6\xC0\x7 ARM32,ARMv6
+
+[UXTAHcc]
+reg32,reg32,reg32 \x86\xFA\x10\xF0\x80 THUMB32,ARMv6T2
+reg32,reg32,reg32,shifterop \x86\xFA\x10\xF0\x80 THUMB32,ARMv6T2
+
+reg32,reg32,reg32 \x16\x6\xF0\x7 ARM32,ARMv6
+reg32,reg32,reg32,shifterop \x16\x6\xF0\x7 ARM32,ARMv6
-[SXTABcc]
-[SXTAB16cc]
-[SXTAHcc]
[SXTBcc]
+reglo,reglo \x61\xB2\x40 THUMB,ARMv6
+
+reg32,reg32 \x86\xFA\x4F\xF0\x80 THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x86\xFA\x4F\xF0\x80 THUMB32,WIDE,ARMv6T2
+
+reg32,reg32 \x1B\x6\xAF\x7 ARM32,ARMv6
+reg32,reg32,shifterop \x1B\x6\xAF\x7 ARM32,ARMv6
+
[SXTB16cc]
+reg32,reg32 \x86\xFA\x2F\xF0\x80 THUMB32,ARMv6T2
+reg32,reg32,shifterop \x86\xFA\x2F\xF0\x80 THUMB32,ARMv6T2
+
+reg32,reg32 \x1B\x6\x8F\x7 ARM32,ARMv6
+reg32,reg32,shifterop \x1B\x6\x8F\x7 ARM32,ARMv6
+
+[SXTHcc]
+reglo,reglo \x61\xB2\x00 THUMB,ARMv6
+
+reg32,reg32 \x86\xFA\x0F\xF0\x80 THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x86\xFA\x0F\xF0\x80 THUMB32,WIDE,ARMv6T2
+
+reg32,reg32 \x1B\x6\xBF\x7 ARM32,ARMv6
+reg32,reg32,shifterop \x1B\x6\xBF\x7 ARM32,ARMv6
[UXTBcc]
+reglo,reglo \x61\xB2\xC0 THUMB,ARMv6
+
+reg32,reg32 \x86\xFA\x5F\xF0\x80 THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x86\xFA\x5F\xF0\x80 THUMB32,WIDE,ARMv6T2
+
+reg32,reg32 \x1B\x6\xEF\x7 ARM32,ARMv6
+reg32,reg32,shifterop \x1B\x6\xEF\x7 ARM32,ARMv6
+
+[UXTB16cc]
+reg32,reg32 \x86\xFA\x3F\xF0\x80 THUMB32,ARMv6T2
+reg32,reg32,shifterop \x86\xFA\x3F\xF0\x80 THUMB32,ARMv6T2
+
+reg32,reg32 \x1B\x6\xCF\x7 ARM32,ARMv6
+reg32,reg32,shifterop \x1B\x6\xCF\x7 ARM32,ARMv6
+
[UXTHcc]
+reglo,reglo \x61\xB2\x80 THUMB,ARMv6
-[SXTHcc]
+reg32,reg32 \x86\xFA\x1F\xF0\x80 THUMB32,WIDE,ARMv6T2
+reg32,reg32,shifterop \x86\xFA\x1F\xF0\x80 THUMB32,WIDE,ARMv6T2
+
+reg32,reg32 \x1B\x6\xFF\x7 ARM32,ARMv6
+reg32,reg32,shifterop \x1B\x6\xFF\x7 ARM32,ARMv6
[UADD16cc]
+reg32,reg32,reg32 \x80\xFA\x90\xF0\x40 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x50\xF1 ARM32,ARMv6
+
[UADD8cc]
-[UASXcc]
+reg32,reg32,reg32 \x80\xFA\x80\xF0\x40 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x50\xF9 ARM32,ARMv6
-[UBFXcc]
+[UASXcc]
+reg32,reg32,reg32 \x80\xFA\xA0\xF0\x40 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x50\xF3 ARM32,ARMv6
[UHADD16cc]
+reg32,reg32,reg32 \x80\xFA\x90\xF0\x60 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x70\xF1 ARM32,ARMv6
+
[UHADD8cc]
+reg32,reg32,reg32 \x80\xFA\x80\xF0\x60 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x70\xF9 ARM32,ARMv6
+
[UHASXcc]
+reg32,reg32,reg32 \x80\xFA\xA0\xF0\x60 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x70\xF3 ARM32,ARMv6
+
[UHSAXcc]
+reg32,reg32,reg32 \x80\xFA\xE0\xF0\x60 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x70\xF5 ARM32,ARMv6
+
[UHSUB16cc]
-[UHSUB8cc]
+reg32,reg32,reg32 \x80\xFA\xD0\xF0\x60 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x70\xF7 ARM32,ARMv6
-[UMAALcc]
+[UHSUB8cc]
+reg32,reg32,reg32 \x80\xFA\xC0\xF0\x60 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x70\xFF ARM32,ARMv6
[UQADD16cc]
+reg32,reg32,reg32 \x80\xFA\x90\xF0\x50 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x60\xF1 ARM32,ARMv6
+
[UQADD8]
+reg32,reg32,reg32 \x80\xFA\x80\xF0\x50 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x60\xF9 ARM32,ARMv6
+
[UQASXcc]
+reg32,reg32,reg32 \x80\xFA\xA0\xF0\x50 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x60\xF3 ARM32,ARMv6
+
[UQSAXcc]
+reg32,reg32,reg32 \x80\xFA\xE0\xF0\x50 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x60\xF5 ARM32,ARMv6
[UQSUB16cc]
+reg32,reg32,reg32 \x80\xFA\xD0\xF0\x50 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x60\xF7 ARM32,ARMv6
+
[UQSUB8cc]
-[UQSAD8cc]
-[UQSADA8cc]
+reg32,reg32,reg32 \x80\xFA\xC0\xF0\x50 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x60\xFF ARM32,ARMv6
+
+[USAD8cc]
+reg32,reg32,reg32 \x80\xFB\x70\xF0\x00 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x15\x07\x80\x01\xF ARM32,ARMv6
+
+[USADA8cc]
+reg32,reg32,reg32,reg32 \x80\xFB\x70\x0\x00 THUMB32,ARMv6T2
+reg32,reg32,reg32,reg32 \x15\x07\x80\x01 ARM32,ARMv6
[USATcc]
+reg32,immshifter,reg32 \x83\xF3\x80\x0\x0 THUMB32,ARMv6T2
+reg32,immshifter,reg32,shifterop \x83\xF3\x80\x0\x0 THUMB32,ARMv6T2
+
+reg32,immshifter,reg32 \x2A\x6\xE0\x0\x10 ARM32,ARMv6
+reg32,immshifter,reg32,shifterop \x2A\x6\xE0\x0\x10 ARM32,ARMv6
+
[USAT16cc]
+reg32,immshifter,reg32 \x83\xF3\xA0\x0\x0 THUMB32,ARMv6T2
+reg32,immshifter,reg32 \x2A\x6\xE0\xF\x30 ARM32,ARMv6
+
[USAXcc]
+reg32,reg32,reg32 \x80\xFA\xE0\xF0\x40 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x50\xF5 ARM32,ARMv6
[USUB16cc]
-[USUB8cc]
+reg32,reg32,reg32 \x80\xFA\xD0\xF0\x40 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x50\xF7 ARM32,ARMv6
-[UXTABcc]
-[UXTAB16cc]
-[UXTAHcc]
-[UXTB16cc]
+[USUB8cc]
+reg32,reg32,reg32 \x80\xFA\xC0\xF0\x40 THUMB32,ARMv6T2
+reg32,reg32,reg32 \x16\x06\x50\xFF ARM32,ARMv6
[WFEcc]
+void \x64\xBF\x20 THUMB,ARMv7
+void \x2F\x3\x20\xF0\x2 ARM32,ARMv6K
+
[WFIcc]
+void \x64\xBF\x30 THUMB,ARMv7
+void \x2F\x3\x20\xF0\x3 ARM32,ARMv6K
+
[YIELDcc]
+void \x64\xBF\x10 THUMB,ARMv7
+void \x2F\x3\x20\xF0\x1 ARM32,ARMv6K
+
+;
+; vfp instructions
+;
+[FABSDcc]
+vreg,vreg \x92\xEE\xB0\xA\xC0\0 THUMB32,VFPv2
+vreg,vreg \x42\xE\xB0\xA\xC0\0 ARM32,VFPv2
+
+[FABSScc]
+vreg,vreg \x92\xEE\xB0\xA\xC0\1 THUMB32,VFPv2
+vreg,vreg \x42\xE\xB0\xA\xC0\1 ARM32,VFPv2
+
+[FADDDcc]
+vreg,vreg,vreg \x92\xEE\x30\xA\x0\0 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x30\xA\x0\0 ARM32,VFPv2
+
+[FADDScc]
+vreg,vreg,vreg \x92\xEE\x30\xA\x0\1 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x30\xA\x0\1 ARM32,VFPv2
+
+[FCMPDcc]
+vreg,vreg \x92\xEE\xB4\xA\x40\0 THUMB32,VFPv2
+vreg,vreg \x42\xE\xB4\xA\x40\0 ARM32,VFPv2
+
+[FCMPScc]
+vreg,vreg \x92\xEE\xB4\xA\x40\1 THUMB32,VFPv2
+vreg,vreg \x42\xE\xB4\xA\x40\1 ARM32,VFPv2
+
+[FCMPEDcc]
+vreg,vreg \x92\xEE\xB4\xA\xC0\0 THUMB32,VFPv2
+vreg,vreg \x42\xE\xB4\xA\xC0\0 ARM32,VFPv2
+
+[FCMPEScc]
+vreg,vreg \x92\xEE\xB4\xA\xC0\1 THUMB32,VFPv2
+vreg,vreg \x42\xE\xB4\xA\xC0\1 ARM32,VFPv2
+
+[FCMPZDcc]
+vreg \x92\xEE\xB5\xA\x40\0 THUMB32,VFPv2
+vreg \x42\xE\xB5\xA\x40\0 ARM32,VFPv2
+
+[FCMPZScc]
+vreg \x92\xEE\xB5\xA\x40\1 THUMB32,VFPv2
+vreg \x42\xE\xB5\xA\x40\1 ARM32,VFPv2
+
+[FCMPEZDcc]
+vreg \x92\xEE\xB5\xA\xC0\0 THUMB32,VFPv2
+vreg \x42\xE\xB5\xA\xC0\0 ARM32,VFPv2
+
+[FCMPEZScc]
+vreg \x92\xEE\xB5\xA\xC0\1 THUMB32,VFPv2
+vreg \x42\xE\xB5\xA\xC0\1 ARM32,VFPv2
+
+[FCPYDcc]
+vreg,vreg \x43\xEE\xB0\xB\x40 THUMB32,VFPv2
+vreg,vreg \x43\xE\xB0\xB\x40 ARM32,VFPv2
+
+[FCPYScc]
+vreg,vreg \x43\xEE\xB0\xA\x40 THUMB32,VFPv2
+vreg,vreg \x43\xE\xB0\xA\x40 ARM32,VFPv2
+
+[FCVTDScc]
+vreg,vreg \x43\xEE\xB7\xA\xC0 THUMB32,VFPv2
+vreg,vreg \x43\xE\xB7\xA\xC0 ARM32,VFPv2
+
+[FCVTSDcc]
+vreg,vreg \x43\xEE\xB7\xB\xC0 THUMB32,VFPv2
+vreg,vreg \x43\xE\xB7\xB\xC0 ARM32,VFPv2
+
+[FDIVDcc]
+vreg,vreg,vreg \x92\xEE\x80\xA\x0\0 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x80\xA\x0\0 ARM32,VFPv2
+
+[FDIVScc]
+vreg,vreg,vreg \x92\xEE\x80\xA\x0\1 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x80\xA\x0\1 ARM32,VFPv2
+
+[FLDDcc]
+vreg,memam2 \x95\xED\x10\xA THUMB32,VFPv2
+vreg,memam2 \x45\xD\x10\xA ARM32,VFPv2
+
+[FLDMcc]
+memam4,reglist \x94\xEC\x10\xA THUMB32,VFPv2
+reg32,reglist \x94\xEC\x10\xA THUMB32,VFPv2
+memam4,reglist \x44\xC\x10\xA ARM32,VFPv2
+reg32,reglist \x44\xC\x10\xA ARM32,VFPv2
+
+[FLDScc]
+vreg,memam2 \x95\xED\x10\xA THUMB32,VFPv2
+vreg,memam2 \x45\xD\x10\xA ARM32,VFPv2
+
+[FMACDcc]
+vreg,vreg,vreg \x92\xEE\x0\xA\x00\0 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x0\xA\x00\0 ARM32,VFPv2
+
+[FMACScc]
+vreg,vreg,vreg \x92\xEE\x0\xA\x00\1 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x0\xA\x00\1 ARM32,VFPv2
+
+[FMDHRcc]
+
+[FMDLRcc]
+
+[FMRDHcc]
+
+[FMRDLcc]
+
+[FMRScc]
+reg32,vreg \x90\xEE\x10\xA\x10 THUMB32,VFPv2
+reg32,vreg \x40\xE\x10\xA\x10 ARM32,VFPv2
+
+[FMRXcc]
+reg32,regf \x91\xEE\xF0\xA\x10 THUMB32,VFPv2
+regf,regf \x91\xEE\xF0\xA\x10 THUMB32,VFPv2
+reg32,regf \x41\xE\xF0\xA\x10 ARM32,VFPv2
+regf,regf \x41\xE\xF0\xA\x10 ARM32,VFPv2
+
+[FMSCDcc]
+vreg,vreg,vreg \x92\xEE\x10\xA\x00\0 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x10\xA\x00\0 ARM32,VFPv2
+
+[FMSCScc]
+vreg,vreg,vreg \x92\xEE\x10\xA\x00\1 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x10\xA\x00\1 ARM32,VFPv2
+
+[FMSRcc]
+vreg,reg32 \x90\xEE\x00\xA\x10 THUMB32,VFPv2
+vreg,reg32 \x40\xE\x00\xA\x10 ARM32,VFPv2
+
+[FMSTATcc]
+void \x80\xEE\xF1\xFA\x10 THUMB32,VFPv2
+void \x2F\xE\xF1\xFA\x10 ARM32,VFPv2
+
+[FMULDcc]
+vreg,vreg,vreg \x92\xEE\x20\xA\x0\0 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x20\xA\x0\0 ARM32,VFPv2
+
+[FMULScc]
+vreg,vreg,vreg \x92\xEE\x20\xA\x0\1 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x20\xA\x0\1 ARM32,VFPv2
+
+[FMXRcc]
+regf,reg32 \x91\xEE\xE0\xA\x10 THUMB32,VFPv2
+regf,reg32 \x41\xE\xE0\xA\x10 ARM32,VFPv2
+
+[FNEGDcc]
+vreg,vreg \x92\xEE\xB1\xA\x40\0 THUMB32,VFPv2
+vreg,vreg \x42\xE\xB1\xA\x40\0 ARM32,VFPv2
+
+[FNEGScc]
+vreg,vreg \x92\xEE\xB1\xA\x40\1 THUMB32,VFPv2
+vreg,vreg \x42\xE\xB1\xA\x40\1 ARM32,VFPv2
+
+[FNMACDcc]
+vreg,vreg,vreg \x92\xEE\x00\xA\x40\0 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x00\xA\x40\0 ARM32,VFPv2
+
+[FNMACScc]
+vreg,vreg,vreg \x92\xEE\x00\xA\x40\1 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x00\xA\x40\1 ARM32,VFPv2
+
+[FNMSCDcc]
+vreg,vreg,vreg \x92\xEE\x10\xA\x40\0 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x10\xA\x40\0 ARM32,VFPv2
+
+[FNMSCScc]
+vreg,vreg,vreg \x92\xEE\x10\xA\x40\1 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x10\xA\x40\1 ARM32,VFPv2
+
+[FNMULDcc]
+vreg,vreg,vreg \x92\xEE\x20\xA\x40\0 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x20\xA\x40\0 ARM32,VFPv2
+
+[FNMULScc]
+vreg,vreg,vreg \x92\xEE\x20\xA\x40\1 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x20\xA\x40\1 ARM32,VFPv2
+
+[FSITODcc]
+vreg,vreg \x43\xEE\xB8\xB\xC0 THUMB32,VFPv2
+vreg,vreg \x43\xE\xB8\xB\xC0 ARM32,VFPv2
+
+[FSITOScc]
+vreg,vreg \x43\xEE\xB8\xA\xC0 THUMB32,VFPv2
+vreg,vreg \x43\xE\xB8\xA\xC0 ARM32,VFPv2
+
+[FSQRTDcc]
+vreg,vreg \x92\xEE\xB1\xA\xC0\0 THUMB32,VFPv2
+vreg,vreg \x42\xE\xB1\xA\xC0\0 ARM32,VFPv2
+
+[FSQRTScc]
+vreg,vreg \x92\xEE\xB1\xA\xC0\1 THUMB32,VFPv2
+vreg,vreg \x42\xE\xB1\xA\xC0\1 ARM32,VFPv2
+
+[FSUBDcc]
+vreg,vreg,vreg \x92\xEE\x30\xA\x40\0 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x30\xA\x40\0 ARM32,VFPv2
+
+[FSUBScc]
+vreg,vreg,vreg \x92\xEE\x30\xA\x40\1 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x30\xA\x40\1 ARM32,VFPv2
+
+[FTOSIDcc]
+vreg,vreg \x43\xEE\xBD\xB\x40 THUMB32,VFPv2
+vreg,vreg \x43\xE\xBD\xB\x40 ARM32,VFPv2
+
+[FTOSIScc]
+vreg,vreg \x43\xEE\xBD\xA\x40 THUMB32,VFPv2
+vreg,vreg \x43\xE\xBD\xA\x40 ARM32,VFPv2
+
+[FTOUIDcc]
+vreg,vreg \x43\xEE\xBC\xB\x40 THUMB32,VFPv2
+vreg,vreg \x43\xE\xBC\xB\x40 ARM32,VFPv2
+
+[FTOUIScc]
+vreg,vreg \x43\xEE\xBC\xA\x40 THUMB32,VFPv2
+vreg,vreg \x43\xE\xBC\xA\x40 ARM32,VFPv2
+
+[FUITODcc]
+vreg,vreg \x43\xEE\xB8\xB\x40 THUMB32,VFPv2
+vreg,vreg \x43\xE\xB8\xB\x40 ARM32,VFPv2
+
+[FUITOScc]
+vreg,vreg \x43\xEE\xB8\xA\x40 THUMB32,VFPv2
+vreg,vreg \x43\xE\xB8\xA\x40 ARM32,VFPv2
+
+[FMDRRcc]
+
+[FMRRDcc]
; Thumb-2
[POP]
+reglist \x69\xBC THUMB,ARMv4T
+reglist \x26\x8B ARM32,ARMv4
[PUSH]
+reglist \x69\xB4 THUMB,ARMv4T
+reglist \x26\x80 ARM32,ARMv4
[SDIVcc]
+reg32,reg32,reg32 \x80\xFB\x90\xF0\xF0 THUMB32,ARMv7R,ARMv7M
+reg32,reg32,reg32 \x15\x07\x10\x01\xF ARM32,ARMv7
[UDIVcc]
+reg32,reg32,reg32 \x80\xFB\xB0\xF0\xF0 THUMB32,ARMv7R,ARMv7M
+reg32,reg32,reg32 \x15\x07\x30\x01\xF ARM32,ARMv7
[MOVTcc]
+reg32,imm \x81\xF2\xC0\x0\x0 THUMB32,ARMv6T2
+reg32,immshifter \x81\xF2\xC0\x0\x0 THUMB32,ARMv6T2
+
+reg32,imm \x2C\x3\x40 ARM32,ARMv6T2
+reg32,immshifter \x2C\x3\x40 ARM32,ARMv6T2
[IT]
+condition \x6A\xBF\x08\x00 THUMB,ARMv6T2
+condition \xFE ARM32,ARMv4
[ITE]
+condition \x6A\xBF\x04\x88 THUMB,ARMv6T2
+condition \xFE ARM32,ARMv4
[ITT]
+condition \x6A\xBF\x04\x08 THUMB,ARMv6T2
+condition \xFE ARM32,ARMv4
[ITEE]
+condition \x6A\xBF\x02\xCC THUMB,ARMv6T2
+condition \xFE ARM32,ARMv4
[ITTE]
+condition \x6A\xBF\x02\x4C THUMB,ARMv6T2
+condition \xFE ARM32,ARMv4
[ITET]
+condition \x6A\xBF\x02\x8C THUMB,ARMv6T2
+condition \xFE ARM32,ARMv4
[ITTT]
+condition \x6A\xBF\x02\x0C THUMB,ARMv6T2
+condition \xFE ARM32,ARMv4
[ITEEE]
+condition \x6A\xBF\x01\xEE THUMB,ARMv6T2
+condition \xFE ARM32,ARMv4
[ITTEE]
+condition \x6A\xBF\x01\x6E THUMB,ARMv6T2
+condition \xFE ARM32,ARMv4
[ITETE]
+condition \x6A\xBF\x01\xAE THUMB,ARMv6T2
+condition \xFE ARM32,ARMv4
[ITTTE]
+condition \x6A\xBF\x01\x2E THUMB,ARMv6T2
+condition \xFE ARM32,ARMv4
[ITEET]
+condition \x6A\xBF\x01\xCE THUMB,ARMv6T2
+condition \xFE ARM32,ARMv4
[ITTET]
+condition \x6A\xBF\x01\x4E THUMB,ARMv6T2
+condition \xFE ARM32,ARMv4
[ITETT]
+condition \x6A\xBF\x01\x8E THUMB,ARMv6T2
+condition \xFE ARM32,ARMv4
[ITTTT]
+condition \x6A\xBF\x01\x0E THUMB,ARMv6T2
+condition \xFE ARM32,ARMv4
+
+[TBBcc]
+memam2 \x8E\xE8\xD0\xF0\x00 THUMB32,ARMv6T2
-[TBB]
-[TBH]
+[TBHcc]
+memam2 \x8E\xE8\xD0\xF0\x10 THUMB32,ARMv6T2
[MOVW]
+reg32,imm32 \x2C\x3\x0 ARM32,ARMv6T2
+reg32,immshifter \x2C\x3\x0 ARM32,ARMv6T2
+
+reg32,imm32 \x81\xF2\x40\x0\x0 THUMB32,ARMv6T2
+reg32,immshifter \x81\xF2\x40\x0\x0 THUMB32,ARMv6T2
[CBZ]
+reglo,immshifter \x68\xB1 THUMB,ARMv6T2
+reglo,memam2 \x68\xB1 THUMB,ARMv6T2
+
[CBNZ]
+reglo,immshifter \x68\xB9 THUMB,ARMv6T2
+reglo,memam2 \x68\xB9 THUMB,ARMv6T2
+
+; VFP
+[VABScc]
+vreg,vreg \x92\xEE\xB0\xA\xC0 THUMB32,VFPv2
+vreg,vreg \x42\xE\xB0\xA\xC0 ARM32,VFPv2
+
+[VADDcc]
+vreg,vreg,vreg \x92\xEE\x30\xA\x0 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x30\xA\x0 ARM32,VFPv2
+
+[VCMPcc]
+vreg,vreg \x92\xEE\xB4\xA\x40 THUMB32,VFPv2
+vreg,immshifter \x92\xEE\xB5\xA\x40 THUMB32,VFPv2
+vreg,vreg \x42\xE\xB4\xA\x40 ARM32,VFPv2
+vreg,immshifter \x42\xE\xB5\xA\x40 ARM32,VFPv2
+
+[VCMPEcc]
+vreg,vreg \x92\xEE\xB4\xA\xC0 THUMB32,VFPv2
+vreg,immshifter \x92\xEE\xB5\xA\xC0 THUMB32,VFPv2
+vreg,vreg \x42\xE\xB4\xA\xC0 ARM32,VFPv2
+vreg,immshifter \x42\xE\xB5\xA\xC0 ARM32,VFPv2
+
+[VCVTcc]
+vreg,vreg \x93\xEE\xB8\xA\xC0 THUMB32,VFPv2
+vreg,vreg,immshifter \x93\xEE\xBA\xA\x40 THUMB32,VFPv3
+vreg,vreg \x43\xE\xB8\xA\xC0 ARM32,VFPv2
+vreg,vreg,immshifter \x43\xE\xBA\xA\x40 ARM32,VFPv3
+
+[VCVTRcc]
+vreg,vreg \x93\xEE\xB8\xA\x40 THUMB32,VFPv2
+vreg,vreg \x43\xE\xB8\xA\x40 ARM32,VFPv2
+
+[VDIVcc]
+vreg,vreg,vreg \x92\xEE\x80\xA\x0 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x80\xA\x0 ARM32,VFPv2
+
+[VMRScc]
+reg32,regf \x91\xEE\xF0\xA\x10 THUMB32,VFPv2
+regf,regf \x91\xEE\xF0\xA\x10 THUMB32,VFPv2
+reg32,regf \x41\xE\xF0\xA\x10 ARM32,VFPv2
+regf,regf \x41\xE\xF0\xA\x10 ARM32,VFPv2
+
+[VMSRcc]
+regf,reg32 \x91\xEE\xE0\xA\x10 THUMB32,VFPv2
+regf,reg32 \x41\xE\xE0\xA\x10 ARM32,VFPv2
+
+[VMLAcc]
+vreg,vreg,vreg \x92\xEE\x0\xA\x00 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x0\xA\x00 ARM32,VFPv2
+
+[VMLScc]
+vreg,vreg,vreg \x92\xEE\x0\xA\x40 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x0\xA\x40 ARM32,VFPv2
+
+[VMULcc]
+vreg,vreg,vreg \x92\xEE\x20\xA\x0 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x20\xA\x0 ARM32,VFPv2
+
+[VNMLAcc]
+vreg,vreg,vreg \x92\xEE\x10\xA\x40 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x10\xA\x40 ARM32,VFPv2
+
+[VNMLScc]
+vreg,vreg,vreg \x92\xEE\x10\xA\x00 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x10\xA\x00 ARM32,VFPv2
+
+[VNMULcc]
+vreg,vreg,vreg \x92\xEE\x20\xA\x40 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x20\xA\x40 ARM32,VFPv2
-; FPv4-s16 - ARMv7M floating point
-[VABS]
-[VADD]
-[VCMP]
-[VCMPE]
-[VCVT]
-[VDIV]
-[VLDM]
-[VLDR]
-[VMOV]
-[VMRS]
-[VMSR]
-[VMUL]
-[VMLA]
-[VMLS]
-[VNMLA]
-[VNMLS]
[VFMA]
+vreg,vreg,vreg \x92\xEE\xA0\xA\x00 THUMB32,VFPv4
+vreg,vreg,vreg \x42\xE\xA0\xA\x00 ARM32,VFPv4
+
[VFMS]
+vreg,vreg,vreg \x92\xEE\xA0\xA\x40 THUMB32,VFPv4
+vreg,vreg,vreg \x42\xE\xA0\xA\x40 ARM32,VFPv4
+
[VFNMA]
+vreg,vreg,vreg \x92\xEE\x90\xA\x00 THUMB32,VFPv4
+vreg,vreg,vreg \x42\xE\x90\xA\x00 ARM32,VFPv4
+
[VFNMS]
-[VNEG]
-[VNMUL]
-[VPOP]
-[VPUSH]
+vreg,vreg,vreg \x92\xEE\x90\xA\x40 THUMB32,VFPv4
+vreg,vreg,vreg \x42\xE\x90\xA\x40 ARM32,VFPv4
+
+[VNEGcc]
+vreg,vreg \x92\xEE\xB1\xA\x40 THUMB32,VFPv2
+vreg,vreg \x42\xE\xB1\xA\x40 ARM32,VFPv2
+
[VSQRT]
-[VSTM]
-[VSTR]
+vreg,vreg \x92\xEE\xB1\xA\xC0 THUMB32,VFPv2
+vreg,vreg \x42\xE\xB1\xA\xC0 ARM32,VFPv2
+
[VSUB]
+vreg,vreg,vreg \x92\xEE\x30\xA\x40 THUMB32,VFPv2
+vreg,vreg,vreg \x42\xE\x30\xA\x40 ARM32,VFPv2
+
+[DMBcc]
+immshifter \x80\xF3\xBF\x8F\x50 THUMB32,ARMv7
+immshifter \x2E\xF5\x7F\xF0\x50 ARM32,ARMv7
+
+[ISBcc]
+immshifter \x80\xF3\xBF\x8F\x60 THUMB32,ARMv7
+immshifter \x2E\xF5\x7F\xF0\x60 ARM32,ARMv7
+
+[DSBcc]
+immshifter \x80\xF3\xBF\x8F\x40 THUMB32,ARMv7
+immshifter \x2E\xF5\x7F\xF0\x40 ARM32,ARMv7
+
+[SMCcc]
+immshifter \x2E\x01\x60\x00\x70 ARM32,ARMv7
+imm32 \x2E\x01\x60\x00\x70 ARM32,ARMv7
; Thumb armv6-m (gcc)
-[NEG]
-[SVC]
+[NEGcc]
+
+[SVCcc]
+immshifter \x61\xDF\x0 THUMB,ARMv4T
+imm32 \x61\xDF\x0 THUMB,ARMv4T
+
+immshifter \x2\x0F ARM32,ARMv4
+imm32 \x2\x0F ARM32,ARMv4
+
+[BXJcc]
+reg32 \x80\xF3\xC0\x8F\x0 THUMB32,ARMv6T2
+reg32 \x3\x01\x2F\xFF\x20 ARM32,ARMv5TEJ
+
+; Undefined mnemonic
+[UDF]
+immshifter \x61\xDE\x0 THUMB,ARMv4T
+void void ARM32,ARMv4T
+
+; FPA
+
+
+[TANcc]
+fpureg,fpureg \xA1\1\x15 ARM32,FPA
+fpureg,immshifter \xA1\1\x15 ARM32,FPA
+
+[SQTcc]
+fpureg,fpureg \xA1\1\x9 ARM32,FPA
+fpureg,immshifter \xA1\1\x9 ARM32,FPA
+
+[SUFcc]
+fpureg,fpureg,fpureg \xA1\0\x4 ARM32,FPA
+fpureg,fpureg,immshifter \xA1\0\x4 ARM32,FPA
+
+[RSFcc]
+fpureg,fpureg,fpureg \xA1\0\x6 ARM32,FPA
+fpureg,fpureg,immshifter \xA1\0\x6 ARM32,FPA
+
+[RNDcc]
+fpureg,fpureg \xA1\1\x7 ARM32,FPA
+fpureg,immshifter \xA1\1\x7 ARM32,FPA
+
+[POLcc]
+fpureg,fpureg,fpureg \xA1\0\x18 ARM32,FPA
+fpureg,fpureg,immshifter \xA1\0\x18 ARM32,FPA
+
+[RDFcc]
+fpureg,fpureg,fpureg \xA1\0\xA ARM32,FPA
+fpureg,fpureg,immshifter \xA1\0\xA ARM32,FPA
+
+[RFScc]
+reg32 \xA2\xE\x3 ARM32,FPA
+
+[RFCcc]
+reg32 \xA2\xE\x5 ARM32,FPA
+
+[WFCcc]
+reg32 \xA2\xE\x4 ARM32,FPA
+
+[RMFcc]
+fpureg,fpureg,fpureg \xA1\0\x10 ARM32,FPA
+fpureg,fpureg,immshifter \xA1\0\x10 ARM32,FPA
+[RPWcc]
+fpureg,fpureg,fpureg \xA1\0\xC ARM32,FPA
+fpureg,fpureg,immshifter \xA1\0\xC ARM32,FPA
+
+[MNFcc]
+fpureg,fpureg \xA1\1\x3 ARM32,FPA
+fpureg,immshifter \xA1\1\x3 ARM32,FPA
+
+[MUFcc]
+fpureg,fpureg,fpureg \xA1\0\x2 ARM32,FPA
+fpureg,fpureg,immshifter \xA1\0\x2 ARM32,FPA
+
+[ABScc]
+fpureg,fpureg \xA1\1\x5 ARM32,FPA
+fpureg,immshifter \xA1\1\x5 ARM32,FPA
+
+[ACScc]
+fpureg,fpureg \xA1\1\x19 ARM32,FPA
+fpureg,immshifter \xA1\1\x19 ARM32,FPA
+
+[ASNcc]
+fpureg,fpureg \xA1\1\x17 ARM32,FPA
+fpureg,immshifter \xA1\1\x17 ARM32,FPA
+
+[ATNcc]
+fpureg,fpureg \xA1\1\x1B ARM32,FPA
+fpureg,immshifter \xA1\1\x1B ARM32,FPA
+
+[CNFcc]
+fpureg,fpureg \xA2\xE\xB0 ARM32,FPA
+fpureg,immshifter \xA2\xE\xB0 ARM32,FPA
+
+[CNFEcc]
+fpureg,fpureg \xA2\xE\xF0 ARM32,FPA
+fpureg,immshifter \xA2\xE\xF0 ARM32,FPA
+
+[COScc]
+fpureg,fpureg \xA1\1\x13 ARM32,FPA
+fpureg,immshifter \xA1\1\x13 ARM32,FPA
+
+[DVFcc]
+fpureg,fpureg,fpureg \xA1\0\x8 ARM32,FPA
+fpureg,fpureg,immshifter \xA1\0\x8 ARM32,FPA
+
+[EXPcc]
+fpureg,fpureg \xA1\1\xF ARM32,FPA
+fpureg,immshifter \xA1\1\xF ARM32,FPA
+
+[FDVcc]
+fpureg,fpureg,fpureg \xA1\0\x14 ARM32,FPA
+fpureg,fpureg,immshifter \xA1\0\x14 ARM32,FPA
+
+[FLTcc]
+fpureg,reg32 \xA2\xE\x00 ARM32,FPA
+
+[FIXcc]
+reg32,fpureg \xA2\xE\x10 ARM32,FPA
+
+[FMLcc]
+fpureg,fpureg,fpureg \xA1\0\x12 ARM32,FPA
+fpureg,fpureg,immshifter \xA1\0\x12 ARM32,FPA
+
+[FRDcc]
+fpureg,fpureg,fpureg \xA1\0\x16 ARM32,FPA
+fpureg,fpureg,immshifter \xA1\0\x16 ARM32,FPA
+
+[LGNcc]
+fpureg,fpureg \xA1\1\xD ARM32,FPA
+fpureg,immshifter \xA1\1\xD ARM32,FPA
+
+[LOGcc]
+fpureg,fpureg \xA1\1\xB ARM32,FPA
+fpureg,immshifter \xA1\1\xB ARM32,FPA
\ No newline at end of file
{ don't edit, this file is generated from armins.dat }
-105;
+952;
{ 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,
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,
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,
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,
A_SMLALTT,
A_SMLAWB,
A_SMLAWT,
+A_VLDM,
+A_VSTM,
+A_VPOP,
+A_VPUSH,
+A_VLDR,
+A_VSTR,
A_SMULBB,
A_SMULBT,
A_SMULTB,
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,
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,
A_LSR,
A_LSL,
A_ROR,
+A_RRX,
+A_UMAAL,
A_SHADD16,
A_SHADD8,
A_SHASX,
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,
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
);
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
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
(
opcode : A_NONE;
ops : 0;
- optypes : (ot_none,ot_none,ot_none,ot_none);
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
code : #0;
flags : if_none
),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #107#65#64;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#241#64#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_ADC;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#235#64#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
(
opcode : A_ADC;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #4#0#160;
- flags : if_arm7
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #128#235#64#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ADC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #128#241#64#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_ADC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#235#64#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
),
(
opcode : A_ADC;
ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
- code : #5#0#160;
- flags : if_arm7
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #128#235#64#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ADC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #4#0#160;
+ flags : if_arm32 or if_armv4
),
(
opcode : A_ADC;
ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
code : #6#0#160;
- flags : if_arm7
+ flags : if_arm32 or if_armv4
),
(
opcode : A_ADC;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
code : #7#2#160;
- flags : if_arm7
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #97#68#0;
+ flags : if_thumb or if_armv4t
),
(
opcode : A_ADD;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #4#0#128;
- flags : if_arm7
+ optypes : (ot_reglo,ot_reglo,ot_reglo,ot_none,ot_none,ot_none);
+ code : #96#24#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #96#28#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ADD;
+ ops : 3;
+ optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #96#28#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #107#48#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ADD;
+ ops : 3;
+ optypes : (ot_reglo,ot_regsp,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #100#168#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ADD;
+ ops : 3;
+ optypes : (ot_regsp,ot_regsp,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #100#176#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ADD;
+ ops : 3;
+ optypes : (ot_reg32,ot_regsp,ot_reg32,ot_none,ot_none,ot_none);
+ code : #100#68#104;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_regsp,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #100#68#133;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#241#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ADD;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#235#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ADD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #128#235#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ADD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #128#241#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ADD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#235#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
),
(
opcode : A_ADD;
ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
- code : #5#0#128;
- flags : if_arm7
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #128#235#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ADD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #4#0#128;
+ flags : if_arm32 or if_armv4
),
(
opcode : A_ADD;
ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
code : #6#0#128;
- flags : if_arm7
+ flags : if_arm32 or if_armv4
),
(
opcode : A_ADD;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
code : #7#2#128;
- flags : if_arm7
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ADDW;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #129#242#0#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_ADF;
+ ops : 3;
+ optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+ code : #161#0#0;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_ADF;
+ ops : 3;
+ optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #161#0#0;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_ADR;
+ ops : 2;
+ optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #103#160#0#2;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ADR;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+ code : #103#160#0#2;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ADR;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none);
+ code : #129#242#175#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ADR;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #129#242#175#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ADR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #129#242#175#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ADR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #51#2#15;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #107#64#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#240#0#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_AND;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#234#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
),
(
opcode : A_AND;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #4#0#0;
- flags : if_arm7
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #128#234#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_AND;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #128#240#0#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_AND;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#234#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
),
(
opcode : A_AND;
ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
- code : #5#0#0;
- flags : if_arm7
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #128#234#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_AND;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #4#0#0;
+ flags : if_arm32 or if_armv4
),
(
opcode : A_AND;
ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
code : #6#0#0;
- flags : if_arm7
+ flags : if_arm32 or if_armv4
),
(
opcode : A_AND;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
code : #7#2#0;
- flags : if_arm7
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_B;
+ ops : 1;
+ optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #98#224#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_B;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #98#224#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_B;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #98#224#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_B;
+ ops : 1;
+ optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #99#208#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_B;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #99#208#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_B;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #99#208#0;
+ flags : if_thumb or if_armv4t
),
(
opcode : A_B;
ops : 1;
- optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
code : #1#10;
- flags : if_arm7
+ flags : if_arm32 or if_armv4
),
(
opcode : A_B;
ops : 1;
- optypes : (ot_immediate24,ot_none,ot_none,ot_none);
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
code : #1#10;
- flags : if_arm7
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_BIC;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #107#67#128;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_BIC;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#240#32#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_BIC;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#234#32#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_BIC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #128#234#32#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_BIC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #128#240#32#0#0;
+ flags : if_thumb32 or if_armv6t2
),
(
opcode : A_BIC;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #4#1#192;
- flags : if_arm7
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#234#32#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
),
(
opcode : A_BIC;
ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
- code : #5#1#192;
- flags : if_arm7
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #128#234#32#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_BIC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #6#1#192;
+ flags : if_arm32 or if_armv4
),
(
opcode : A_BIC;
ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
code : #6#1#192;
- flags : if_arm7
+ flags : if_arm32 or if_armv4
),
(
opcode : A_BIC;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
code : #7#3#192;
- flags : if_arm7
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_BL;
+ ops : 1;
+ optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #141#240#208;
+ flags : if_thumb or if_thumb32 or if_armv4t
+ ),
+ (
+ opcode : A_BL;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #141#240#208;
+ flags : if_thumb or if_thumb32 or if_armv4t
+ ),
+ (
+ opcode : A_BL;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #141#240#208;
+ flags : if_thumb or if_thumb32 or if_armv4t
),
(
opcode : A_BL;
ops : 1;
- optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
+ optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
code : #1#11;
- flags : if_arm7
+ flags : if_arm32 or if_armv4
),
(
opcode : A_BL;
ops : 1;
- optypes : (ot_immediate24,ot_none,ot_none,ot_none);
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
code : #1#11;
- flags : if_arm7
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_BLX;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #98#71#128;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_BLX;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #141#240#192;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_BLX;
+ ops : 1;
+ optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #141#240#192;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_BLX;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #141#240#192;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_BLX;
+ ops : 1;
+ optypes : (ot_immediate24,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #40#250;
+ flags : if_arm32 or if_armv5t
+ ),
+ (
+ opcode : A_BLX;
+ ops : 1;
+ optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #40#250;
+ flags : if_arm32 or if_armv5t
+ ),
+ (
+ opcode : A_BLX;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #3#1#47#255#48;
+ flags : if_arm32 or if_armv5t
+ ),
+ (
+ opcode : A_BKPT;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #96#190#0;
+ flags : if_thumb or if_armv5t
+ ),
+ (
+ opcode : A_BKPT;
+ ops : 1;
+ optypes : (ot_immediate,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #49#1#32#112;
+ flags : if_arm32 or if_armv5t
+ ),
+ (
+ opcode : A_BKPT;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #49#1#32#112;
+ flags : if_arm32 or if_armv5t
+ ),
+ (
+ opcode : A_BX;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #98#71#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_BX;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #3#1#47#255#16;
+ flags : if_arm32 or if_armv4t
+ ),
+ (
+ opcode : A_CDP;
+ ops : 2;
+ optypes : (ot_reg8,ot_reg8,ot_none,ot_none,ot_none,ot_none);
+ code : #192#1#16#65;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_CMN;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #107#66#192;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_CMN;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#241#16#15#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_CMN;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#235#16#15#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_CMN;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #128#235#16#15#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_CMN;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #12#1#96;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_CMN;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #14#1#96;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_CMN;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #15#1#96;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #107#66#128;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #97#69#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #107#40#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#241#176#15#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#235#176#15#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_CMP;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #128#235#176#15#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #12#1#64;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_CMP;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #14#1#64;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_CMP;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #15#3#64;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_CMF;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #162#14#144;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_CMF;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #162#14#144;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_CMFE;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #162#14#192;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_CMFE;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #162#14#192;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_STF;
+ ops : 2;
+ optypes : (ot_fpureg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #160#12#0#1#0;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_LDF;
+ ops : 2;
+ optypes : (ot_fpureg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #160#12#16#1#0;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_LFM;
+ ops : 3;
+ optypes : (ot_fpureg,ot_immediate or ot_bits32,ot_memoryam2,ot_none,ot_none,ot_none);
+ code : #160#12#16#2#0;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_LFM;
+ ops : 3;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_memoryam2,ot_none,ot_none,ot_none);
+ code : #160#12#16#2#0;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_CLZ;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#250#176#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_CLZ;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #50#1#111#15#16;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_CPS;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #143#243#175#129#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_CPS;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #70#241#2#0#0;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_CPSID;
+ ops : 1;
+ optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #108#182#112;
+ flags : if_thumb or if_armv6
+ ),
+ (
+ opcode : A_CPSID;
+ ops : 1;
+ optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #143#243#175#134#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_CPSID;
+ ops : 2;
+ optypes : (ot_modeflags,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #143#243#175#135#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_CPSID;
+ ops : 1;
+ optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #70#241#12#0#0;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_CPSID;
+ ops : 2;
+ optypes : (ot_modeflags,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #70#241#14#0#0;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_CPSIE;
+ ops : 1;
+ optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #108#182#96;
+ flags : if_thumb or if_armv6
+ ),
+ (
+ opcode : A_CPSIE;
+ ops : 1;
+ optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #143#243#175#132#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_CPSIE;
+ ops : 2;
+ optypes : (ot_modeflags,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #143#243#175#133#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_CPSIE;
+ ops : 1;
+ optypes : (ot_modeflags,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #70#241#8#0#0;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_CPSIE;
+ ops : 2;
+ optypes : (ot_modeflags,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #70#241#10#0#0;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_EOR;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #107#64#64;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_EOR;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#240#128#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_EOR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#234#128#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_EOR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #128#234#128#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_EOR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #128#240#128#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_EOR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#234#128#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_EOR;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #128#234#128#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_EOR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #4#0#32;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_EOR;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #6#0#32;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_EOR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #7#2#32;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDC;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #209#192#1#17#65;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #105#200;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LDM;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #105#200;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LDM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #140#232#16#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_LDM;
+ ops : 2;
+ optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #140#232#16#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_LDM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #38#129;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDM;
+ ops : 2;
+ optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #38#129;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDRBT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#248#16#14#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_LDRBT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #23#4#112;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDRBT;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #23#4#112;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDRB;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+ code : #101#92#0#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LDRB;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+ code : #102#120#0#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LDRB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#248#16#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_LDRB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #23#4#80;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDR;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+ code : #101#88#0#2;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LDR;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+ code : #102#104#0#2;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LDR;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam5,ot_none,ot_none,ot_none,ot_none);
+ code : #103#152#0#2;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LDR;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+ code : #103#72#0#2;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LDR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#248#80#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_LDR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #23#4#16;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDRH;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+ code : #101#90#0#1;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LDRH;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+ code : #102#136#0#1;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LDRH;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#248#48#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_LDRH;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #34#16#176;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDRSB;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+ code : #101#86#0#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LDRSB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#249#16#0#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_LDRSB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #34#16#208;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDRSB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #35#80#208;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDRSB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none,ot_none);
+ code : #36#80#208;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDRSB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #37#16#208;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDRSH;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+ code : #101#94#0#1;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LDRSH;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#249#48#0#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_LDRSH;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #34#16#240;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDRT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#248#80#14#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_LDRT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #23#4#48;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MCR;
+ ops : 5;
+ optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_none);
+ code : #28#14#0#1;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MCR;
+ ops : 6;
+ optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_immediateshifter);
+ code : #28#14#0#1;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MCR2;
+ ops : 5;
+ optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_none);
+ code : #28#254#0#1;
+ flags : if_arm32 or if_armv5t
+ ),
+ (
+ opcode : A_MCR2;
+ ops : 6;
+ optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_immediateshifter);
+ code : #28#254#0#1;
+ flags : if_arm32 or if_armv5t
+ ),
+ (
+ opcode : A_MRC;
+ ops : 5;
+ optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_none);
+ code : #28#14#16#1;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MRC;
+ ops : 6;
+ optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_immediateshifter);
+ code : #28#14#16#1;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MRC2;
+ ops : 5;
+ optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_none);
+ code : #28#254#16#1;
+ flags : if_arm32 or if_armv5t
+ ),
+ (
+ opcode : A_MRC2;
+ ops : 6;
+ optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_regf,ot_regf,ot_immediateshifter);
+ code : #28#254#16#1;
+ flags : if_arm32 or if_armv5t
+ ),
+ (
+ opcode : A_MCRR;
+ ops : 5;
+ optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_reg32,ot_regf,ot_none);
+ code : #29#12#64#0;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_MCRR2;
+ ops : 5;
+ optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_reg32,ot_regf,ot_none);
+ code : #29#252#64#0;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_MRRC;
+ ops : 5;
+ optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_reg32,ot_regf,ot_none);
+ code : #29#12#80#0;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_MRRC2;
+ ops : 5;
+ optypes : (ot_regf,ot_immediateshifter,ot_reg32,ot_reg32,ot_regf,ot_none);
+ code : #29#252#80#0;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_MLA;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #128#251#0#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_MLA;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #21#0#32#9;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #107#0#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #97#70#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #107#32#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#240#79#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#234#79#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_shifterop,ot_none,ot_none,ot_none,ot_none);
+ code : #8#1#160;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MOV;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #10#1#160;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #11#1#160;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MRS;
+ ops : 2;
+ optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+ code : #150#243#239#128#0;
+ flags : if_thumb32 or if_armv6
+ ),
+ (
+ opcode : A_MRS;
+ ops : 2;
+ optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+ code : #16#1#15;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MSR;
+ ops : 2;
+ optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #150#243#128#128#0;
+ flags : if_thumb32 or if_armv6
+ ),
+ (
+ opcode : A_MSR;
+ ops : 2;
+ optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #18#1#32#240;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MSR;
+ ops : 2;
+ optypes : (ot_regf,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #19#3#32#240;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MSR;
+ ops : 2;
+ optypes : (ot_regs,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #19#3#32#240;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MUL;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #100#67#64;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_MUL;
+ ops : 3;
+ optypes : (ot_reglo,ot_reglo,ot_reglo,ot_none,ot_none,ot_none);
+ code : #100#67#64;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_MUL;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#251#0#240#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_MUL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#251#0#240#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_MUL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #20#0#0#144;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MVF;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#1;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_MVF;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#1;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_MVN;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #107#67#192;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_MVN;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#240#111#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_MVN;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#234#111#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_MVN;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #8#1#224;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MVN;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #10#1#224;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MVN;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #11#1#224;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_VMOV;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #144#238#176#10#64;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMOV;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #64#14#176#10#64;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #144#238#16#10#16;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMOV;
+ ops : 2;
+ optypes : (ot_vreg,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #144#238#0#10#16;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMOV;
+ ops : 2;
+ optypes : (ot_reg32,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #64#14#16#10#16;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMOV;
+ ops : 2;
+ optypes : (ot_vreg,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #64#14#0#10#16;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMOV;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_vreg,ot_vreg,ot_none,ot_none);
+ code : #144#236#80#10#16;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMOV;
+ ops : 4;
+ optypes : (ot_vreg,ot_vreg,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #144#236#64#10#16;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMOV;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_vreg,ot_vreg,ot_none,ot_none);
+ code : #64#12#80#10#16;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMOV;
+ ops : 4;
+ optypes : (ot_vreg,ot_vreg,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #64#12#64#10#16;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMOV;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_vreg,ot_none,ot_none,ot_none);
+ code : #144#236#80#11#16;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMOV;
+ ops : 3;
+ optypes : (ot_vreg,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #144#236#64#11#16;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMOV;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_vreg,ot_none,ot_none,ot_none);
+ code : #64#12#80#11#16;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMOV;
+ ops : 3;
+ optypes : (ot_vreg,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #64#12#64#11#16;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_NOP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #97#191#0;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_NOP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #47#3#32#240#0;
+ flags : if_arm32 or if_armv6k
+ ),
+ (
+ opcode : A_NOP;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #47#225#160#0#0;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ORN;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#240#96#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_ORN;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#234#96#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_ORN;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #128#234#96#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_ORN;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #128#240#96#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_ORN;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#234#96#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_ORN;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #128#234#96#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_ORR;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #107#67#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ORR;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#240#64#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_ORR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#234#64#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ORR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #128#234#64#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ORR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #128#240#64#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_ORR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#234#64#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ORR;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #128#234#64#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ORR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #4#1#128;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ORR;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #5#1#128;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ORR;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #6#1#128;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ORR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #7#3#128;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_RSB;
+ ops : 3;
+ optypes : (ot_reglo,ot_reglo,ot_immediatezero,ot_none,ot_none,ot_none);
+ code : #107#66#64;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_RSB;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#241#192#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_RSB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#235#192#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_RSB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #128#235#192#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_RSB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #128#241#192#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_RSB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#235#192#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_RSB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #128#235#192#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_RSB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #6#0#96;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_RSB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #6#0#96;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_RSB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #7#0#96;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_RSC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #4#0#224;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_RSC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #5#0#224;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_RSC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #6#0#224;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_RSC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #7#2#224;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SBC;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #107#65#128;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_SBC;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#241#96#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SBC;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#235#96#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_SBC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #128#235#96#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_SBC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #128#241#96#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SBC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#235#96#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_SBC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #128#235#96#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_SBC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #4#0#192;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SBC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #5#0#192;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SBC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate,ot_none,ot_none);
+ code : #6#0#192;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SBC;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #6#0#192;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SBC;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #7#2#192;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SFM;
+ ops : 3;
+ optypes : (ot_fpureg,ot_immediate or ot_bits32,ot_memoryam2,ot_none,ot_none,ot_none);
+ code : #160#12#0#2#0;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_SFM;
+ ops : 3;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_memoryam2,ot_none,ot_none,ot_none);
+ code : #160#12#0#2#0;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_SIN;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#17;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_SIN;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#17;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_SMLAL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #133#251#192#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SMLAL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #22#0#224#9;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SMULL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #133#251#128#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SMULL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #22#0#192#9;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_STM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #105#192;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_STM;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #105#192;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_STM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #140#232#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_STM;
+ ops : 2;
+ optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #140#232#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_STM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #38#128;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_STM;
+ ops : 2;
+ optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #38#128;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_STR;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+ code : #101#80#0#2;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_STR;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+ code : #102#96#0#2;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_STR;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam5,ot_none,ot_none,ot_none,ot_none);
+ code : #103#144#0#2;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_STR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#248#64#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_STR;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #23#4#0;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_STRB;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+ code : #101#84#0#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_STRB;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+ code : #102#112#0#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_STRB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#248#0#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_STRB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #23#4#64;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_STRBT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#248#0#14#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_STRBT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #23#4#96;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_STRBT;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #23#4#96;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_STRH;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam3,ot_none,ot_none,ot_none,ot_none);
+ code : #101#82#0#1;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_STRH;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam4,ot_none,ot_none,ot_none,ot_none);
+ code : #102#128#0#1;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_STRH;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#248#32#0#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_STRH;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #34#0#176;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_STRT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#248#64#14#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_STRT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #23#4#32;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_regsp,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #100#176#128;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_SUB;
+ ops : 3;
+ optypes : (ot_regsp,ot_regsp,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #100#176#128;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #96#26#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_SUB;
+ ops : 3;
+ optypes : (ot_reglo,ot_reglo,ot_reglo,ot_none,ot_none,ot_none);
+ code : #96#26#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #96#30#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_SUB;
+ ops : 3;
+ optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #96#30#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reglo,ot_immediate or ot_bits8,ot_none,ot_none,ot_none,ot_none);
+ code : #107#56#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #107#56#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#241#160#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_SUB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#235#160#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_SUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #128#235#160#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_SUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #128#241#160#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_SUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#235#160#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_SUB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #128#235#160#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_SUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #4#0#64;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #4#0#64;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #4#0#64;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SUB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #6#0#64;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SWP;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+ code : #39#16#9;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SWPB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+ code : #39#20#9;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_TEQ;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#240#144#15#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_TEQ;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#234#144#15#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_TEQ;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #128#234#144#15#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_TEQ;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #12#1#32;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_TEQ;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #13#1#32;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_TEQ;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #14#1#32;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_TEQ;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #15#3#32;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_TST;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #107#66#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_TST;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #128#240#16#15#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_TST;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#234#16#15#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_TST;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #128#234#16#15#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_TST;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #12#1#0;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_TST;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #13#1#0;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_TST;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #14#1#0;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_TST;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #15#3#0;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_UMLAL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #133#251#224#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UMLAL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #22#0#160#9;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_UMULL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #133#251#160#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UMULL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #22#0#128#9;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_WFS;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #162#14#2;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_LDRD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+ code : #137#232#80#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_LDRD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+ code : #25#0#0#0#208;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_PLD;
+ ops : 1;
+ optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #135#248#16#240#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_PLD;
+ ops : 1;
+ optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #37#245#80#240#0;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_PLDW;
+ ops : 1;
+ optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #135#248#48#240#0;
+ flags : if_thumb32 or if_armv7
+ ),
+ (
+ opcode : A_PLDW;
+ ops : 1;
+ optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #37#245#16#240#0;
+ flags : if_arm32 or if_armv7
+ ),
+ (
+ opcode : A_QADD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #130#250#128#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_QADD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #26#1#0#5;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_QDADD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #130#250#128#240#144;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_QDADD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #26#1#64#5;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_QDSUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #130#250#128#240#176;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_QDSUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #26#1#96#5;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_QSUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #130#250#128#240#160;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_QSUB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #26#1#32#5;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_SMLABB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #21#1#0#8;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_SMLABT;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #21#1#0#12;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_SMLATB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #21#1#0#10;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_SMLATT;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #21#1#0#14;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_SMLALBB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #22#1#64#8;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_SMLALBT;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #22#1#64#12;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_SMLALTB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #22#1#64#10;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_SMLALTT;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #22#1#64#14;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_SMLAWB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #128#251#48#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SMLAWB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #21#1#32#8;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_SMLAWT;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #128#251#48#0#16;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SMLAWT;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #21#1#32#12;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_VLDM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #148#236#16#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VLDM;
+ ops : 2;
+ optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #148#236#16#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VLDM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #68#12#16#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VLDM;
+ ops : 2;
+ optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #68#12#16#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VSTM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #148#236#0#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VSTM;
+ ops : 2;
+ optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #148#236#0#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VSTM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #68#12#0#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VSTM;
+ ops : 2;
+ optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #68#12#0#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VPOP;
+ ops : 1;
+ optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #148#236#189#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VPOP;
+ ops : 1;
+ optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #68#12#189#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VPUSH;
+ ops : 1;
+ optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #148#237#45#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VPUSH;
+ ops : 1;
+ optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #68#13#45#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VLDR;
+ ops : 2;
+ optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #149#237#16#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VLDR;
+ ops : 2;
+ optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #69#13#16#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VSTR;
+ ops : 2;
+ optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #149#237#0#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VSTR;
+ ops : 2;
+ optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #69#13#0#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_SMULBB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #21#1#96#8#0;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_SMULBT;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #21#1#96#12#0;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_SMULTB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #21#1#96#10#0;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_SMULTT;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #21#1#96#14#0;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_SMULWB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #20#1#32#160;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_SMULWT;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #20#1#32#224;
+ flags : if_arm32 or if_armv5te
+ ),
+ (
+ opcode : A_STRD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+ code : #137#232#64#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_STRD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none);
+ code : #25#0#0#0#240;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDRHT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#248#48#14#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_LDRHT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #25#0#48#0#176;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_STRHT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#248#32#14#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_STRHT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#248#32#14#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_STRHT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #30#0#32#0#176;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDRSBT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#249#16#14#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_LDRSBT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #30#0#48#0#208;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDRSHT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #136#249#48#14#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_LDRSHT;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #30#0#48#0#240;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_FSTD;
+ ops : 2;
+ optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #149#237#0#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSTD;
+ ops : 2;
+ optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #69#13#0#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSTM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #148#236#0#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSTM;
+ ops : 2;
+ optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #148#236#0#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSTM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #68#12#0#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSTM;
+ ops : 2;
+ optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #68#12#0#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSTS;
+ ops : 2;
+ optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #149#237#0#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSTS;
+ ops : 2;
+ optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #69#13#0#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_BFC;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #132#243#111#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_BFC;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediateshifter,ot_immediate or ot_bits32,ot_none,ot_none,ot_none);
+ code : #132#243#111#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_BFC;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #45#7#192#0#31;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_BFC;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediateshifter,ot_immediate or ot_bits32,ot_none,ot_none,ot_none);
+ code : #45#7#192#0#31;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_BFI;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+ code : #132#243#96#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_BFI;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #132#243#96#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_BFI;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+ code : #45#7#192#0#16;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_BFI;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediate or ot_bits32,ot_none,ot_none);
+ code : #45#7#192#0#16;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_CLREX;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #128#243#191#143#47;
+ flags : if_thumb32 or if_armv7
+ ),
+ (
+ opcode : A_CLREX;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #47#245#127#240#31;
+ flags : if_arm32 or if_armv6k
+ ),
+ (
+ opcode : A_LDREX;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+ code : #138#232#80#15#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_LDREX;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+ code : #24#1#144#15#159;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDREXB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+ code : #138#232#208#15#79;
+ flags : if_thumb32 or if_armv7
+ ),
+ (
+ opcode : A_LDREXB;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+ code : #24#1#208#15#159;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDREXD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+ code : #138#232#208#0#127;
+ flags : if_thumb32 or if_armv7
+ ),
+ (
+ opcode : A_LDREXD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+ code : #24#1#176#15#159;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LDREXH;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+ code : #138#232#208#15#95;
+ flags : if_thumb32 or if_armv7
+ ),
+ (
+ opcode : A_LDREXH;
+ ops : 2;
+ optypes : (ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none,ot_none);
+ code : #24#1#240#15#159;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_STREX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+ code : #139#232#64#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_STREX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+ code : #24#1#128#15#144;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_STREXB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+ code : #139#232#192#15#64;
+ flags : if_thumb32 or if_armv7
+ ),
+ (
+ opcode : A_STREXB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+ code : #24#1#192#15#144;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_STREXD;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none);
+ code : #139#232#192#0#112;
+ flags : if_thumb32 or if_armv7
+ ),
+ (
+ opcode : A_STREXD;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none);
+ code : #24#1#160#15#144;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_STREXH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+ code : #139#232#192#15#80;
+ flags : if_thumb32 or if_armv7
+ ),
+ (
+ opcode : A_STREXH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_memoryam6,ot_none,ot_none,ot_none);
+ code : #24#1#224#15#144;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_MLS;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #128#251#0#0#16;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_MLS;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #21#0#96#9;
+ flags : if_arm32 or if_armv6t2
+ ),
+ (
+ opcode : A_PKHBT;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#234#192#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_PKHBT;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #128#234#192#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_PKHBT;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#128#1;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_PKHBT;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #22#6#128#1;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_PKHTB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#234#192#0#16;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_PKHTB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #128#234#192#0#16;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_PKHTB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#128#1;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_PKHTB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #22#6#128#5;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_PLI;
+ ops : 1;
+ optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #135#249#16#240#0;
+ flags : if_thumb32 or if_armv7
+ ),
+ (
+ opcode : A_PLI;
+ ops : 1;
+ optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #37#244#80#240#0;
+ flags : if_arm32 or if_armv7
+ ),
+ (
+ opcode : A_QADD16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#144#240#16;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_QADD16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#32#241;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_QADD8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#128#240#16;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_QADD8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#32#249;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_QASX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#160#240#16;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_QASX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#32#243;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_QSAX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#224#240#16;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_QSAX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#32#245;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_QSUB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#208#240#16;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_QSUB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#32#247;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_QSUB8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#192#240#16;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_QSUB8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#32#255;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_RBIT;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#250#144#240#160;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_RBIT;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #50#6#255#15#48;
+ flags : if_arm32 or if_armv6t2
+ ),
+ (
+ opcode : A_REV;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #97#186#0;
+ flags : if_thumb or if_armv6
+ ),
+ (
+ opcode : A_REV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#250#144#240#128;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_REV;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #50#6#191#15#48;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_REV16;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #97#186#64;
+ flags : if_thumb or if_armv6
+ ),
+ (
+ opcode : A_REV16;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#250#144#240#144;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_REV16;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #50#6#191#15#176;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_REVSH;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #97#186#192;
+ flags : if_thumb or if_armv6
+ ),
+ (
+ opcode : A_REVSH;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#250#144#240#176;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_REVSH;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #50#6#255#15#176;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SADD16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#72#240#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SADD16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#16#241;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SADD8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#64#240#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SADD8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#16#249;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SASX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#80#240#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SASX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#16#243;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SBFX;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+ code : #132#243#64#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SBFX;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+ code : #45#7#160#0#80;
+ flags : if_arm32 or if_armv6t2
+ ),
+ (
+ opcode : A_SEL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#160#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SEL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#128#251;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SETEND;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #43#241#1#0#0;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SEV;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #100#191#64;
+ flags : if_thumb or if_armv7
+ ),
+ (
+ opcode : A_SEV;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #47#3#32#240#4;
+ flags : if_arm32 or if_armv6k
+ ),
+ (
+ opcode : A_ASR;
+ ops : 2;
+ optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #96#1#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ASR;
+ ops : 3;
+ optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #96#1#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ASR;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #107#65#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ASR;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #130#234#79#0#32;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ASR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #130#234#79#0#32;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ASR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#250#64#240#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ASR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#64#240#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ASR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #48#1#160#0#80;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ASR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #48#1#160#0#64;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LSR;
+ ops : 2;
+ optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #96#8#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LSR;
+ ops : 3;
+ optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #96#8#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LSR;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #107#64#192;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LSR;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #130#234#79#0#16;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_LSR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #130#234#79#0#16;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_LSR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#250#32#240#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_LSR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#32#240#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_LSR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #48#1#160#0#48;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LSR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #48#1#160#0#32;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LSL;
+ ops : 2;
+ optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #96#0#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LSL;
+ ops : 3;
+ optypes : (ot_reglo,ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #96#0#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LSL;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #107#64#128;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_LSL;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #130#234#79#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_LSL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #130#234#79#0#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_LSL;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#250#96#240#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_LSL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#96#240#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_LSL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #48#1#160#0#16;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_LSL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #48#1#160#0#0;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #107#65#192;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #130#234#79#0#48;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ROR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #130#234#79#0#48;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ROR;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#250#96#240#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ROR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#96#240#0;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_ROR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #48#1#160#0#112;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ROR;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #48#1#160#0#96;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_RRX;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #128#234#79#0#48;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_RRX;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #48#1#160#0#96;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_UMAAL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #133#251#224#0#96;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UMAAL;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #22#0#64#9;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SHADD16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#144#240#32;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SHADD16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#48#241;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SHADD8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#128#240#32;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SHADD8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#48#249;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SHASX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#160#240#32;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SHASX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#48#243;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SHSAX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#224#240#32;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SHSAX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#48#245;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SHSUB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#208#240#32;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SHSUB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#48#247;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SHSUB8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#192#240#32;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SHSUB8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#48#255;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SMLAD;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #128#251#32#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SMLAD;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #21#7#0#1;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SMLALD;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #133#251#192#0#192;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SMLALD;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #22#7#64#1;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SMLSD;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #128#251#64#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SMLSD;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #21#7#0#5;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SMLSLD;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #133#251#208#0#192;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SMLSLD;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #22#7#64#5;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SMMLA;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #128#251#80#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SMMLA;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #21#7#80#1;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SMMLS;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #128#251#96#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SMMLS;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #21#7#80#13;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SMMUL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#251#80#240#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SMMUL;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #21#7#80#1#15;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SMUAD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#251#32#240#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SMUAD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #21#7#0#1#15;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SMUSD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#251#64#240#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SMUSD;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #21#7#0#5#15;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SSAT;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+ code : #131#243#0#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SSAT;
+ ops : 4;
+ optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #131#243#0#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SSAT;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+ code : #42#6#160#0#16;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SSAT;
+ ops : 4;
+ optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #42#6#160#0#16;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SSAT16;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+ code : #131#243#32#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SSAT16;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+ code : #42#6#160#15#48;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SSAX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#224#240#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SSAX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#16#245;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SSUB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#208#240#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SSUB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#16#247;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SSUB8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#192#240#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SSUB8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#16#255;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SXTAB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #134#250#64#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SXTAB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #134#250#64#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SXTAB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#160#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SXTAB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #22#6#160#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SXTAB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #134#250#32#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SXTAB16;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #134#250#32#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SXTAB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#128#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SXTAB16;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #22#6#128#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SXTAH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #134#250#0#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SXTAH;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #134#250#0#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SXTAH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#176#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SXTAH;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #22#6#176#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UBFX;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+ code : #132#243#192#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UBFX;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_immediateshifter,ot_none,ot_none);
+ code : #45#7#224#0#80;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_UXTAB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #134#250#80#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UXTAB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #134#250#80#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UXTAB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#224#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UXTAB;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #22#6#224#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UXTAB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #134#250#48#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UXTAB16;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #134#250#48#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UXTAB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #134#250#64#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UXTAB16;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #134#250#64#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UXTAB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#192#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UXTAB16;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #22#6#192#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UXTAH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #134#250#16#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UXTAH;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #134#250#16#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UXTAH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#240#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UXTAH;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #22#6#240#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SXTB;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #97#178#64;
+ flags : if_thumb or if_armv6
+ ),
+ (
+ opcode : A_SXTB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #134#250#79#240#128;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_SXTB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #134#250#79#240#128;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_SXTB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #27#6#175#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SXTB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #27#6#175#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SXTB16;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #134#250#47#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SXTB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #134#250#47#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_SXTB16;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #27#6#143#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SXTB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #27#6#143#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SXTH;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #97#178#0;
+ flags : if_thumb or if_armv6
+ ),
+ (
+ opcode : A_SXTH;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #134#250#15#240#128;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_SXTH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #134#250#15#240#128;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_SXTH;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #27#6#191#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_SXTH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #27#6#191#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UXTB;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #97#178#192;
+ flags : if_thumb or if_armv6
+ ),
+ (
+ opcode : A_UXTB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #134#250#95#240#128;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_UXTB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #134#250#95#240#128;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_UXTB;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #27#6#239#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UXTB;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #27#6#239#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UXTB16;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #134#250#63#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UXTB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #134#250#63#240#128;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UXTB16;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #27#6#207#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UXTB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #27#6#207#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UXTH;
+ ops : 2;
+ optypes : (ot_reglo,ot_reglo,ot_none,ot_none,ot_none,ot_none);
+ code : #97#178#128;
+ flags : if_thumb or if_armv6
+ ),
+ (
+ opcode : A_UXTH;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #134#250#31#240#128;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_UXTH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #134#250#31#240#128;
+ flags : if_thumb32 or if_wide or if_armv6t2
+ ),
+ (
+ opcode : A_UXTH;
+ ops : 2;
+ optypes : (ot_reg32,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #27#6#255#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UXTH;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none,ot_none,ot_none);
+ code : #27#6#255#7;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UADD16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#144#240#64;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UADD16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#80#241;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UADD8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#128#240#64;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UADD8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#80#249;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UASX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#160#240#64;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UASX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#80#243;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UHADD16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#144#240#96;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UHADD16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#112#241;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UHADD8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#128#240#96;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UHADD8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#112#249;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UHASX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#160#240#96;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UHASX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#112#243;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UHSAX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#224#240#96;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UHSAX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#112#245;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UHSUB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#208#240#96;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UHSUB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#112#247;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UHSUB8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#192#240#96;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UHSUB8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#112#255;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UQADD16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#144#240#80;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UQADD16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#96#241;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UQADD8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#128#240#80;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UQADD8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#96#249;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UQASX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#160#240#80;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UQASX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#96#243;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UQSAX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#224#240#80;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UQSAX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#96#245;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UQSUB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#208#240#80;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UQSUB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#96#247;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_UQSUB8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#192#240#80;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_UQSUB8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#96#255;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_USAD8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#251#112#240#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_USAD8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #21#7#128#1#15;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_USADA8;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #128#251#112#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_USADA8;
+ ops : 4;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none);
+ code : #21#7#128#1;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_USAT;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+ code : #131#243#128#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_USAT;
+ ops : 4;
+ optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #131#243#128#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_USAT;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+ code : #42#6#224#0#16;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_USAT;
+ ops : 4;
+ optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_shifterop,ot_none,ot_none);
+ code : #42#6#224#0#16;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_USAT16;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+ code : #131#243#160#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_USAT16;
+ ops : 3;
+ optypes : (ot_reg32,ot_immediateshifter,ot_reg32,ot_none,ot_none,ot_none);
+ code : #42#6#224#15#48;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_USAX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#224#240#64;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_USAX;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#80#245;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_USUB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#208#240#64;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_USUB16;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#80#247;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_USUB8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#250#192#240#64;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_USUB8;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #22#6#80#255;
+ flags : if_arm32 or if_armv6
+ ),
+ (
+ opcode : A_WFE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #100#191#32;
+ flags : if_thumb or if_armv7
+ ),
+ (
+ opcode : A_WFE;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #47#3#32#240#2;
+ flags : if_arm32 or if_armv6k
+ ),
+ (
+ opcode : A_WFI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #100#191#48;
+ flags : if_thumb or if_armv7
+ ),
+ (
+ opcode : A_WFI;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #47#3#32#240#3;
+ flags : if_arm32 or if_armv6k
+ ),
+ (
+ opcode : A_YIELD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #100#191#16;
+ flags : if_thumb or if_armv7
+ ),
+ (
+ opcode : A_YIELD;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #47#3#32#240#1;
+ flags : if_arm32 or if_armv6k
+ ),
+ (
+ opcode : A_FABSD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#176#10#192#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FABSD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#176#10#192#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FABSS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#176#10#192#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FABSS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#176#10#192#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FADDD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#48#10#0#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FADDD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#48#10#0#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FADDS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#48#10#0#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FADDS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#48#10#0#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#180#10#64#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#180#10#64#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#180#10#64#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#180#10#64#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPED;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#180#10#192#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPED;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#180#10#192#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPES;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#180#10#192#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPES;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#180#10#192#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPZD;
+ ops : 1;
+ optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#181#10#64#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPZD;
+ ops : 1;
+ optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#181#10#64#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPZS;
+ ops : 1;
+ optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#181#10#64#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPZS;
+ ops : 1;
+ optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#181#10#64#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPEZD;
+ ops : 1;
+ optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#181#10#192#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPEZD;
+ ops : 1;
+ optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#181#10#192#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPEZS;
+ ops : 1;
+ optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#181#10#192#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCMPEZS;
+ ops : 1;
+ optypes : (ot_vreg,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#181#10#192#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCPYD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#238#176#11#64;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCPYD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#14#176#11#64;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCPYS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#238#176#10#64;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCPYS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#14#176#10#64;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCVTDS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#238#183#10#192;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCVTDS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#14#183#10#192;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCVTSD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#238#183#11#192;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FCVTSD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#14#183#11#192;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FDIVD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#128#10#0#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FDIVD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#128#10#0#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FDIVS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#128#10#0#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FDIVS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#128#10#0#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FLDD;
+ ops : 2;
+ optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #149#237#16#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FLDD;
+ ops : 2;
+ optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #69#13#16#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FLDM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #148#236#16#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FLDM;
+ ops : 2;
+ optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #148#236#16#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FLDM;
+ ops : 2;
+ optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #68#12#16#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FLDM;
+ ops : 2;
+ optypes : (ot_reg32,ot_reglist,ot_none,ot_none,ot_none,ot_none);
+ code : #68#12#16#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FLDS;
+ ops : 2;
+ optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #149#237#16#10;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FLDS;
+ ops : 2;
+ optypes : (ot_vreg,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #69#13#16#10;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMACD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#0#10#0#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMACD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#0#10#0#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMACS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#0#10#0#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMACS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#0#10#0#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMRS;
+ ops : 2;
+ optypes : (ot_reg32,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #144#238#16#10#16;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMRS;
+ ops : 2;
+ optypes : (ot_reg32,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #64#14#16#10#16;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMRX;
+ ops : 2;
+ optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+ code : #145#238#240#10#16;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMRX;
+ ops : 2;
+ optypes : (ot_regf,ot_regf,ot_none,ot_none,ot_none,ot_none);
+ code : #145#238#240#10#16;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMRX;
+ ops : 2;
+ optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+ code : #65#14#240#10#16;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMRX;
+ ops : 2;
+ optypes : (ot_regf,ot_regf,ot_none,ot_none,ot_none,ot_none);
+ code : #65#14#240#10#16;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMSCD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#16#10#0#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMSCD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#16#10#0#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMSCS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#16#10#0#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMSCS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#16#10#0#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMSR;
+ ops : 2;
+ optypes : (ot_vreg,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #144#238#0#10#16;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMSR;
+ ops : 2;
+ optypes : (ot_vreg,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #64#14#0#10#16;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMSTAT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #128#238#241#250#16;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMSTAT;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #47#14#241#250#16;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMULD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#32#10#0#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMULD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#32#10#0#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMULS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#32#10#0#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMULS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#32#10#0#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMXR;
+ ops : 2;
+ optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #145#238#224#10#16;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FMXR;
+ ops : 2;
+ optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #65#14#224#10#16;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNEGD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#177#10#64#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNEGD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#177#10#64#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNEGS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#177#10#64#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNEGS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#177#10#64#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNMACD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#0#10#64#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNMACD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#0#10#64#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNMACS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#0#10#64#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNMACS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#0#10#64#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNMSCD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#16#10#64#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNMSCD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#16#10#64#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNMSCS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#16#10#64#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNMSCS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#16#10#64#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNMULD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#32#10#64#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNMULD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#32#10#64#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNMULS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#32#10#64#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FNMULS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#32#10#64#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSITOD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#238#184#11#192;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSITOD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#14#184#11#192;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSITOS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#238#184#10#192;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSITOS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#14#184#10#192;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSQRTD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#177#10#192#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSQRTD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#177#10#192#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSQRTS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#177#10#192#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSQRTS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#177#10#192#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSUBD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#48#10#64#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSUBD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#48#10#64#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSUBS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#48#10#64#1;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FSUBS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#48#10#64#1;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FTOSID;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#238#189#11#64;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FTOSID;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#14#189#11#64;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FTOSIS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#238#189#10#64;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FTOSIS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#14#189#10#64;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FTOUID;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#238#188#11#64;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FTOUID;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#14#188#11#64;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FTOUIS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#238#188#10#64;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FTOUIS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#14#188#10#64;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FUITOD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#238#184#11#64;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FUITOD;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#14#184#11#64;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_FUITOS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#238#184#10#64;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_FUITOS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#14#184#10#64;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #105#188;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_POP;
+ ops : 1;
+ optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #38#139;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #105#180;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_PUSH;
+ ops : 1;
+ optypes : (ot_reglist,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #38#128;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SDIV;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#251#144#240#240;
+ flags : if_thumb32 or if_armv7r or if_armv7m
+ ),
+ (
+ opcode : A_SDIV;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #21#7#16#1#15;
+ flags : if_arm32 or if_armv7
+ ),
+ (
+ opcode : A_UDIV;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #128#251#176#240#240;
+ flags : if_thumb32 or if_armv7r or if_armv7m
+ ),
+ (
+ opcode : A_UDIV;
+ ops : 3;
+ optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none,ot_none,ot_none);
+ code : #21#7#48#1#15;
+ flags : if_arm32 or if_armv7
+ ),
+ (
+ opcode : A_MOVT;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none,ot_none,ot_none,ot_none);
+ code : #129#242#192#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_MOVT;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #129#242#192#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_MOVT;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate,ot_none,ot_none,ot_none,ot_none);
+ code : #44#3#64;
+ flags : if_arm32 or if_armv6t2
+ ),
+ (
+ opcode : A_MOVT;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #44#3#64;
+ flags : if_arm32 or if_armv6t2
+ ),
+ (
+ opcode : A_IT;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #106#191#8#0;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_IT;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #254;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ITE;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #106#191#4#136;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_ITE;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #254;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ITT;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #106#191#4#8;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_ITT;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #254;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ITEE;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #106#191#2#204;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_ITEE;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #254;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ITTE;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #106#191#2#76;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_ITTE;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #254;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ITET;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #106#191#2#140;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_ITET;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #254;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ITTT;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #106#191#2#12;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_ITTT;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #254;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ITEEE;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #106#191#1#238;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_ITEEE;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #254;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ITTEE;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #106#191#1#110;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_ITTEE;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #254;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ITETE;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #106#191#1#174;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_ITETE;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #254;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ITTTE;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #106#191#1#46;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_ITTTE;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #254;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ITEET;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #106#191#1#206;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_ITEET;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #254;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ITTET;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #106#191#1#78;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_ITTET;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #254;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ITETT;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #106#191#1#142;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_ITETT;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #254;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_ITTTT;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #106#191#1#14;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_ITTTT;
+ ops : 1;
+ optypes : (ot_condition,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #254;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_TBB;
+ ops : 1;
+ optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #142#232#208#240#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_TBH;
+ ops : 1;
+ optypes : (ot_memoryam2,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #142#232#208#240#16;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_MOVW;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none);
+ code : #44#3#0;
+ flags : if_arm32 or if_armv6t2
+ ),
+ (
+ opcode : A_MOVW;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #44#3#0;
+ flags : if_arm32 or if_armv6t2
+ ),
+ (
+ opcode : A_MOVW;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none);
+ code : #129#242#64#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_MOVW;
+ ops : 2;
+ optypes : (ot_reg32,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #129#242#64#0#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_CBZ;
+ ops : 2;
+ optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #104#177;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_CBZ;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #104#177;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_CBNZ;
+ ops : 2;
+ optypes : (ot_reglo,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #104#185;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_CBNZ;
+ ops : 2;
+ optypes : (ot_reglo,ot_memoryam2,ot_none,ot_none,ot_none,ot_none);
+ code : #104#185;
+ flags : if_thumb or if_armv6t2
+ ),
+ (
+ opcode : A_VABS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#176#10#192;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VABS;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#176#10#192;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VADD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#48#10#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VADD;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#48#10#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VCMP;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#180#10#64;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VCMP;
+ ops : 2;
+ optypes : (ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#181#10#64;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VCMP;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#180#10#64;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VCMP;
+ ops : 2;
+ optypes : (ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#181#10#64;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VCMPE;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#180#10#192;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VCMPE;
+ ops : 2;
+ optypes : (ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#181#10#192;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VCMPE;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#180#10#192;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VCMPE;
+ ops : 2;
+ optypes : (ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#181#10#192;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VCVT;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #147#238#184#10#192;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VCVT;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #147#238#186#10#64;
+ flags : if_thumb32 or if_vfpv3
+ ),
+ (
+ opcode : A_VCVT;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#14#184#10#192;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VCVT;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #67#14#186#10#64;
+ flags : if_arm32 or if_vfpv3
+ ),
+ (
+ opcode : A_VCVTR;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #147#238#184#10#64;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VCVTR;
+ ops : 2;
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #67#14#184#10#64;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VDIV;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#128#10#0;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VDIV;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#128#10#0;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMRS;
+ ops : 2;
+ optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+ code : #145#238#240#10#16;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMRS;
+ ops : 2;
+ optypes : (ot_regf,ot_regf,ot_none,ot_none,ot_none,ot_none);
+ code : #145#238#240#10#16;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMRS;
+ ops : 2;
+ optypes : (ot_reg32,ot_regf,ot_none,ot_none,ot_none,ot_none);
+ code : #65#14#240#10#16;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMRS;
+ ops : 2;
+ optypes : (ot_regf,ot_regf,ot_none,ot_none,ot_none,ot_none);
+ code : #65#14#240#10#16;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMSR;
+ ops : 2;
+ optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #145#238#224#10#16;
+ flags : if_thumb32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMSR;
+ ops : 2;
+ optypes : (ot_regf,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #65#14#224#10#16;
+ flags : if_arm32 or if_vfpv2
+ ),
+ (
+ opcode : A_VMLA;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#0#10#0;
+ flags : if_thumb32 or if_vfpv2
),
(
- opcode : A_BLX;
- ops : 1;
- optypes : (ot_memory or ot_bits32,ot_none,ot_none,ot_none);
- code : #15#15;
- flags : if_arm7
+ opcode : A_VMLA;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#0#10#0;
+ flags : if_arm32 or if_vfpv2
),
(
- opcode : A_BLX;
- ops : 1;
- optypes : (ot_immediate24,ot_none,ot_none,ot_none);
- code : #15#15;
- flags : if_arm7
+ opcode : A_VMLS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#0#10#64;
+ flags : if_thumb32 or if_vfpv2
),
(
- opcode : A_BX;
- ops : 1;
- optypes : (ot_reg32,ot_none,ot_none,ot_none);
- code : #3#1#47#255#16;
- flags : if_arm7
+ opcode : A_VMLS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#0#10#64;
+ flags : if_arm32 or if_vfpv2
),
(
- opcode : A_CDP;
- ops : 2;
- optypes : (ot_reg8,ot_reg8,ot_none,ot_none);
- code : #192#1#16#65;
- flags : if_arm7
+ opcode : A_VMUL;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#32#10#0;
+ flags : if_thumb32 or if_vfpv2
),
(
- opcode : A_CMN;
- ops : 2;
- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
- code : #12#1#96;
- flags : if_arm7
+ opcode : A_VMUL;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#32#10#0;
+ flags : if_arm32 or if_vfpv2
),
(
- opcode : A_CMN;
+ opcode : A_VNMLA;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #13#1#96;
- flags : if_arm7
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#16#10#64;
+ flags : if_thumb32 or if_vfpv2
),
(
- opcode : A_CMN;
+ opcode : A_VNMLA;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
- code : #14#1#96;
- flags : if_arm7
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#16#10#64;
+ flags : if_arm32 or if_vfpv2
),
(
- opcode : A_CMN;
- ops : 2;
- optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
- code : #15#3#96;
- flags : if_arm7
+ opcode : A_VNMLS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#16#10#0;
+ flags : if_thumb32 or if_vfpv2
),
(
- opcode : A_CMP;
- ops : 2;
- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
- code : #12#1#64;
- flags : if_arm7
+ opcode : A_VNMLS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#16#10#0;
+ flags : if_arm32 or if_vfpv2
),
(
- opcode : A_CMP;
+ opcode : A_VNMUL;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #13#1#64;
- flags : if_arm7
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#32#10#64;
+ flags : if_thumb32 or if_vfpv2
),
(
- opcode : A_CMP;
+ opcode : A_VNMUL;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
- code : #14#1#64;
- flags : if_arm7
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#32#10#64;
+ flags : if_arm32 or if_vfpv2
),
(
- opcode : A_CMP;
- ops : 2;
- optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
- code : #15#3#64;
- flags : if_arm7
+ opcode : A_VFMA;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#160#10#0;
+ flags : if_thumb32 or if_vfpv4
),
(
- opcode : A_CLZ;
- ops : 2;
- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
- code : #39#1#1;
- flags : if_arm7
+ opcode : A_VFMA;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#160#10#0;
+ flags : if_arm32 or if_vfpv4
),
(
- opcode : A_EOR;
+ opcode : A_VFMS;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #4#0#32;
- flags : if_arm7
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#160#10#64;
+ flags : if_thumb32 or if_vfpv4
),
(
- opcode : A_EOR;
- ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
- code : #5#0#32;
- flags : if_arm7
+ opcode : A_VFMS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#160#10#64;
+ flags : if_arm32 or if_vfpv4
),
(
- opcode : A_EOR;
- ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
- code : #6#0#32;
- flags : if_arm7
+ opcode : A_VFNMA;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#144#10#0;
+ flags : if_thumb32 or if_vfpv4
),
(
- opcode : A_EOR;
+ opcode : A_VFNMA;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
- code : #7#2#32;
- flags : if_arm7
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#144#10#0;
+ flags : if_arm32 or if_vfpv4
),
(
- opcode : A_LDC;
- ops : 2;
- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
- code : #209#192#1#17#65;
- flags : if_arm7
+ opcode : A_VFNMS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#144#10#64;
+ flags : if_thumb32 or if_vfpv4
),
(
- opcode : A_LDM;
- ops : 2;
- optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none);
- code : #38#129;
- flags : if_arm7
+ opcode : A_VFNMS;
+ ops : 3;
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#144#10#64;
+ flags : if_arm32 or if_vfpv4
),
(
- opcode : A_LDRB;
+ opcode : A_VNEG;
ops : 2;
- optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
- code : #23#7#16;
- flags : if_arm7
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#177#10#64;
+ flags : if_thumb32 or if_vfpv2
),
(
- opcode : A_LDR;
+ opcode : A_VNEG;
ops : 2;
- optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
- code : #23#5#16;
- flags : if_arm7
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#177#10#64;
+ flags : if_arm32 or if_vfpv2
),
(
- opcode : A_LDRH;
+ opcode : A_VSQRT;
ops : 2;
- optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
- code : #34#80#176;
- flags : if_arm7
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #146#238#177#10#192;
+ flags : if_thumb32 or if_vfpv2
),
(
- opcode : A_LDRH;
+ opcode : A_VSQRT;
ops : 2;
- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
- code : #35#80#176;
- flags : if_arm7
+ optypes : (ot_vreg,ot_vreg,ot_none,ot_none,ot_none,ot_none);
+ code : #66#14#177#10#192;
+ flags : if_arm32 or if_vfpv2
),
(
- opcode : A_LDRH;
+ opcode : A_VSUB;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
- code : #36#80#176;
- flags : if_arm7
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #146#238#48#10#64;
+ flags : if_thumb32 or if_vfpv2
),
(
- opcode : A_LDRH;
+ opcode : A_VSUB;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #37#16#176;
- flags : if_arm7
+ optypes : (ot_vreg,ot_vreg,ot_vreg,ot_none,ot_none,ot_none);
+ code : #66#14#48#10#64;
+ flags : if_arm32 or if_vfpv2
),
(
- opcode : A_LDRSB;
- ops : 2;
- optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
- code : #34#80#208;
- flags : if_arm7
+ opcode : A_DMB;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #128#243#191#143#80;
+ flags : if_thumb32 or if_armv7
),
(
- opcode : A_LDRSB;
- ops : 2;
- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
- code : #35#80#208;
- flags : if_arm7
+ opcode : A_DMB;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #46#245#127#240#80;
+ flags : if_arm32 or if_armv7
),
(
- opcode : A_LDRSB;
- ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
- code : #36#80#208;
- flags : if_arm7
+ opcode : A_ISB;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #128#243#191#143#96;
+ flags : if_thumb32 or if_armv7
),
(
- opcode : A_LDRSB;
- ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #37#16#208;
- flags : if_arm7
+ opcode : A_ISB;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #46#245#127#240#96;
+ flags : if_arm32 or if_armv7
),
(
- opcode : A_LDRSH;
- ops : 2;
- optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
- code : #34#80#240;
- flags : if_arm7
+ opcode : A_DSB;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #128#243#191#143#64;
+ flags : if_thumb32 or if_armv7
),
(
- opcode : A_LDRSH;
- ops : 2;
- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
- code : #35#80#240;
- flags : if_arm7
+ opcode : A_DSB;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #46#245#127#240#64;
+ flags : if_arm32 or if_armv7
),
(
- opcode : A_LDRSH;
- ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
- code : #36#80#240;
- flags : if_arm7
+ opcode : A_SMC;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #46#1#96#0#112;
+ flags : if_arm32 or if_armv7
),
(
- opcode : A_LDRSH;
- ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #37#16#240;
- flags : if_arm7
+ opcode : A_SMC;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #46#1#96#0#112;
+ flags : if_arm32 or if_armv7
),
(
- opcode : A_LFM;
- ops : 3;
- optypes : (ot_reg32,ot_immediate or ot_bits8,ot_fpureg,ot_none);
- code : #240#2#1;
- flags : if_fpa
+ opcode : A_SVC;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #97#223#0;
+ flags : if_thumb or if_armv4t
),
(
- opcode : A_MLA;
- ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
- code : #21#0#32#144;
- flags : if_arm7
+ opcode : A_SVC;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #97#223#0;
+ flags : if_thumb or if_armv4t
),
(
- opcode : A_MRS;
+ opcode : A_SVC;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #2#15;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_SVC;
+ ops : 1;
+ optypes : (ot_immediate or ot_bits32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #2#15;
+ flags : if_arm32 or if_armv4
+ ),
+ (
+ opcode : A_BXJ;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #128#243#192#143#0;
+ flags : if_thumb32 or if_armv6t2
+ ),
+ (
+ opcode : A_BXJ;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #3#1#47#255#32;
+ flags : if_arm32 or if_armv5tej
+ ),
+ (
+ opcode : A_UDF;
+ ops : 1;
+ optypes : (ot_immediateshifter,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #97#222#0;
+ flags : if_thumb or if_armv4t
+ ),
+ (
+ opcode : A_UDF;
+ ops : 0;
+ optypes : (ot_none,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #0;
+ flags : if_arm32 or if_armv4t
+ ),
+ (
+ opcode : A_TAN;
ops : 2;
- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
- code : #16#1#15;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#21;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_MSR;
+ opcode : A_TAN;
ops : 2;
- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
- code : #17#1#41#240;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#21;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_MSR;
+ opcode : A_SQT;
ops : 2;
- optypes : (ot_regf,ot_reg32,ot_none,ot_none);
- code : #18#1#40#240;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#9;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_MSR;
+ opcode : A_SQT;
ops : 2;
- optypes : (ot_regf,ot_immediate,ot_none,ot_none);
- code : #19#3#40#240;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#9;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_MUL;
+ opcode : A_SUF;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #20#0#0#144;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+ code : #161#0#4;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_MVF;
- ops : 2;
- optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none);
- code : #242;
- flags : if_fpa
+ opcode : A_SUF;
+ ops : 3;
+ optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #161#0#4;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_MVF;
- ops : 2;
- optypes : (ot_fpureg,ot_immediatefpu,ot_none,ot_none);
- code : #242;
- flags : if_fpa
+ opcode : A_RSF;
+ ops : 3;
+ optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+ code : #161#0#6;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_ORR;
+ opcode : A_RSF;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #4#1#128;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #161#0#6;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_ORR;
- ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
- code : #5#1#128;
- flags : if_arm7
+ opcode : A_RND;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#7;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_ORR;
- ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
- code : #6#1#128;
- flags : if_arm7
+ opcode : A_RND;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#7;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_ORR;
+ opcode : A_POL;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
- code : #7#3#128;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+ code : #161#0#24;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_RSB;
+ opcode : A_POL;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #4#0#96;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #161#0#24;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_RSB;
- ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
- code : #5#0#96;
- flags : if_arm7
+ opcode : A_RDF;
+ ops : 3;
+ optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+ code : #161#0#10;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_RSB;
- ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
- code : #6#0#96;
- flags : if_arm7
+ opcode : A_RDF;
+ ops : 3;
+ optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #161#0#10;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_RSB;
- ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
- code : #7#2#96;
- flags : if_arm7
+ opcode : A_RFS;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #162#14#3;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_RSC;
- ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #4#0#224;
- flags : if_arm7
+ opcode : A_RFC;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #162#14#5;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_RSC;
- ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
- code : #5#0#224;
- flags : if_arm7
+ opcode : A_WFC;
+ ops : 1;
+ optypes : (ot_reg32,ot_none,ot_none,ot_none,ot_none,ot_none);
+ code : #162#14#4;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_RSC;
- ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
- code : #6#0#224;
- flags : if_arm7
+ opcode : A_RMF;
+ ops : 3;
+ optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+ code : #161#0#16;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_RSC;
+ opcode : A_RMF;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
- code : #7#2#224;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #161#0#16;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_SBC;
+ opcode : A_RPW;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #4#0#192;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+ code : #161#0#12;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_SBC;
- ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
- code : #5#0#192;
- flags : if_arm7
+ opcode : A_RPW;
+ ops : 3;
+ optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #161#0#12;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_SBC;
- ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_immediate);
- code : #6#0#192;
- flags : if_arm7
+ opcode : A_MNF;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#3;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_SBC;
+ opcode : A_MNF;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#3;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_MUF;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
- code : #7#2#192;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+ code : #161#0#2;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_SFM;
+ opcode : A_MUF;
ops : 3;
- optypes : (ot_reg32,ot_immediate or ot_bits8,ot_fpureg,ot_none);
- code : #240#2#0;
- flags : if_fpa
+ optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #161#0#2;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_SMLAL;
- ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
- code : #22#0#224#144;
- flags : if_arm7
+ opcode : A_ABS;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#5;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_SMULL;
- ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
- code : #22#0#192#144;
- flags : if_arm7
+ opcode : A_ABS;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#5;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_STM;
+ opcode : A_ACS;
ops : 2;
- optypes : (ot_memoryam4,ot_reglist,ot_none,ot_none);
- code : #38#128;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#25;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_STR;
+ opcode : A_ACS;
ops : 2;
- optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
- code : #23#4#0;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#25;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_STRB;
+ opcode : A_ASN;
ops : 2;
- optypes : (ot_reg32,ot_memoryam2,ot_none,ot_none);
- code : #23#6#0;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#23;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_STRH;
+ opcode : A_ASN;
ops : 2;
- optypes : (ot_reg32,ot_immediate or ot_bits32,ot_none,ot_none);
- code : #34#64#176;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#23;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_STRH;
+ opcode : A_ATN;
ops : 2;
- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
- code : #35#64#176;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#27;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_STRH;
- ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate or ot_bits32,ot_none);
- code : #36#64#176;
- flags : if_arm7
+ opcode : A_ATN;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#27;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_STRH;
- ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #37#0#176;
- flags : if_arm7
+ opcode : A_CNF;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #162#14#176;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_SUB;
- ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_shifterop,ot_none);
- code : #4#0#64;
- flags : if_arm7
+ opcode : A_CNF;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #162#14#176;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_SUB;
- ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediateshifter,ot_none);
- code : #4#0#64;
- flags : if_arm7
+ opcode : A_CNFE;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #162#14#240;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_SUB;
- ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #4#0#64;
- flags : if_arm7
+ opcode : A_CNFE;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #162#14#240;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_SWI;
- ops : 1;
- optypes : (ot_immediate,ot_none,ot_none,ot_none);
- code : #2#15;
- flags : if_arm7
+ opcode : A_COS;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#19;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_SWP;
+ opcode : A_COS;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#19;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_DVF;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #39#1#144;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+ code : #161#0#8;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_SWPB;
+ opcode : A_DVF;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #39#1#144;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #161#0#8;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_TEQ;
+ opcode : A_EXP;
ops : 2;
- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
- code : #12#1#32;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#15;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_TEQ;
+ opcode : A_EXP;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#15;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_FDV;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #13#1#32;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+ code : #161#0#20;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_TEQ;
+ opcode : A_FDV;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
- code : #14#1#32;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #161#0#20;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_TEQ;
+ opcode : A_FLT;
ops : 2;
- optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
- code : #15#3#32;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_reg32,ot_none,ot_none,ot_none,ot_none);
+ code : #162#14#0;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_TST;
+ opcode : A_FIX;
ops : 2;
- optypes : (ot_reg32,ot_reg32,ot_none,ot_none);
- code : #12#1#0;
- flags : if_arm7
+ optypes : (ot_reg32,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #162#14#16;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_TST;
+ opcode : A_FML;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_none);
- code : #13#1#0;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+ code : #161#0#18;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_TST;
+ opcode : A_FML;
ops : 3;
- optypes : (ot_reg32,ot_reg32,ot_immediate,ot_none);
- code : #14#1#0;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #161#0#18;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_TST;
+ opcode : A_FRD;
+ ops : 3;
+ optypes : (ot_fpureg,ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none);
+ code : #161#0#22;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_FRD;
+ ops : 3;
+ optypes : (ot_fpureg,ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none);
+ code : #161#0#22;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_LGN;
ops : 2;
- optypes : (ot_reg32,ot_immediate,ot_none,ot_none);
- code : #15#3#0;
- flags : if_arm7
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#13;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_UMLAL;
- ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
- code : #22#0#160#144;
- flags : if_arm7
+ opcode : A_LGN;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#13;
+ flags : if_arm32 or if_fpa
),
(
- opcode : A_UMULL;
- ops : 4;
- optypes : (ot_reg32,ot_reg32,ot_reg32,ot_reg32);
- code : #22#0#128#144;
- flags : if_arm7
+ opcode : A_LOG;
+ ops : 2;
+ optypes : (ot_fpureg,ot_fpureg,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#11;
+ flags : if_arm32 or if_fpa
+ ),
+ (
+ opcode : A_LOG;
+ ops : 2;
+ optypes : (ot_fpureg,ot_immediateshifter,ot_none,ot_none,ot_none,ot_none);
+ code : #161#1#11;
+ flags : if_arm32 or if_fpa
)
);
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;
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
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;
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;
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));
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;
intreg,
tmpmmreg : tregister;
reg64 : tregister64;
- op : tasmop;
begin
if assigned(shuffle) and
not(shufflescalar(shuffle)) then
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
intreg,
tmpmmreg : tregister;
reg64 : tregister64;
- op : tasmop;
begin
if assigned(shuffle) and
not(shufflescalar(shuffle)) then
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;
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;
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;
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;
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
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;
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;
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
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;
first_mm_imreg = $30;
{ TODO: Calculate bsstart}
- regnumber_count_bsstart = 64;
+ regnumber_count_bsstart = 128;
regnumber_table : array[tregisterindex] of tregister = (
{$i rarmnum.inc}
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 }
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;
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');
var
t : aint;
i : longint;
- imm : byte;
begin
{Loading 0-255 is simple}
if (d and $FF) = d then
) 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;
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;
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
end;
+ function elf_arm_encodeflags: longword;
+ begin
+ result:=EF_ARM_EABI_VER5;
+ end;
+
{*****************************************************************************
Initialize
*****************************************************************************}
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;
fpu_vfpv2,
fpu_vfpv3,
fpu_vfpv3_d16,
- fpu_fpv4_s16
+ fpu_fpv4_s16,
+ fpu_vfpv4
);
tcontrollertype =
'VFPV2',
'VFPV3',
'VFPV3_D16',
- 'FPV4_S16'
+ 'FPV4_S16',
+ 'VFPV4'
);
{ 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],
var
op : TAsmOp;
singleprec: boolean;
+ pf: TOpPostfix;
begin
pass_left_right;
if (nf_swapped in flags) then
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
procedure tarmaddnode.second_cmpfloat;
var
op: TAsmOp;
+ pf: TOpPostfix;
begin
pass_left_right;
if (nf_swapped in flags) then
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:
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;
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
procedure tarminlinenode.second_abs_real;
var
singleprec: boolean;
- op: TAsmOp;
+ pf: TOpPostfix;
begin
load_fpu_location(singleprec);
case current_settings.fputype of
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));
procedure tarminlinenode.second_sqr_real;
var
singleprec: boolean;
- op: TAsmOp;
+ pf: TOpPostfix;
begin
load_fpu_location(singleprec);
case current_settings.fputype of
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));
procedure tarminlinenode.second_sqrt_real;
var
singleprec: boolean;
- op: TAsmOp;
+ pf: TOpPostfix;
begin
load_fpu_location(singleprec);
case current_settings.fputype of
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;
procedure tarmunaryminusnode.second_float;
var
op: tasmop;
+ pf: TOpPostfix;
begin
secondpass(left);
case current_settings.fputype of
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
uses
globtype,
+ symtype,
cgbase,cpubase,nmem,ncgmem;
type
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
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;
(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);
cpubase;
type
+
tarmattreader = class(tattreader)
actoppostfix : TOpPostfix;
actwideformat : boolean;
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;
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),
(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;
{ 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
do_error;
oper.opr.ref.shiftimm := shift;
test_end(require_rbracket);
- end;
+ end
+ else
+ test_end(require_rbracket);
end
else
begin
else if (actasmpattern='ROR') then
handlepara(SM_ROR)
else if (actasmpattern='RRX') then
- handlepara(SM_ROR)
+ handlepara(SM_RRX)
else
result:=false;
end
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;
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;
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
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;
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
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);
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
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;
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
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;
initialization
RegisterAsmMode(asmmode_arm_att_info);
+ RegisterAsmMode(asmmode_arm_att_unified_info);
RegisterAsmMode(asmmode_arm_standard_info);
end.
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);
0,
0,
0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
0
{ don't edit, this file is generated from armreg.dat }
-124
+131
tregister($0500001F),
tregister($05000020),
tregister($05000021),
-tregister($05000022)
+tregister($05000022),
+tregister($05000023),
+tregister($05000024),
+tregister($05000025),
+tregister($05000026),
+tregister($05000027),
+tregister($05000028),
+tregister($05000029)
120,
121,
122,
-123
+123,
+124,
+125,
+126,
+127,
+128,
+129,
+130
{ don't edit, this file is generated from armreg.dat }
0,
110,
+129,
92,
+128,
+130,
120,
121,
123,
23,
24,
122,
+127,
90,
+124,
114,
113,
111,
117,
+126,
+125,
109,
119,
118,
53,
28,
55,
-71,
56,
58,
59,
68,
29,
70,
+71,
31,
32,
34,
0,
0,
0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
0
's29',
'd14',
's30',
-'s21',
+'s31',
'd15',
'd16',
'd17',
'basepri',
'basepri_max',
'faultmask',
-'control'
+'control',
+'fpsid',
+'mvfr1',
+'mvfr0',
+'fpexc',
+'apsr_nzcvq',
+'apsr_g',
+'apsr_nzcvqg'
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;
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.
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
asd_reference:
{ ignore for now, but should be added}
;
+{$ifdef ARM}
+ asd_thumb_func:
+ ObjData.ThumbFunc:=true;
+{$endif ARM}
else
internalerror(2010011101);
end;
asd_reference:
{ ignore for now, but should be added}
;
+ asd_thumb_func:
+ { ignore for now, but should be added}
+ ;
else
internalerror(2010011102);
end;
objsymend : TObjSymbol;
zerobuf : array[0..63] of byte;
relative_reloc: boolean;
+ tmp : word;
begin
fillchar(zerobuf,sizeof(zerobuf),0);
fillchar(objsym,sizeof(objsym),0);
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;
,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}
);
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',
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;
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. }
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
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;
addressmode : taddressmode;
shiftmode : tshiftmode;
{$endif arm}
+{$ifdef aarch64}
+ symboldata : tlinkedlistitem;
+ shiftimm : byte;
+ addressmode : taddressmode;
+ shiftmode : tshiftmode;
+{$endif aarch64}
{$ifdef avr}
addressmode : taddressmode;
{$endif avr}
{$define cpurox}
{$define cputargethasfixedstack}
{$define cpurefshaveindexreg}
+ {$define SUPPORT_GET_FRAME}
{$endif aarch64}
{$IFDEF MACOS}
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;
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);
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;
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
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 }
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
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
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
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);
encodereloc: @elf_i386_encodeReloc;
loadreloc: @elf_i386_loadReloc;
loadsection: nil;
+ encodeflags: nil;
);
as_i386_elf32_info : tasminfo =
uses
globtype,
+ symtype,
cgbase,cpuinfo,cpubase,
node,nmem,ncgmem,nx86mem,ni86mem;
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
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,
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;
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;
{ 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;
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;
{ 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;
encodereloc: @elf_mips_encodeReloc;
loadreloc: @elf_mips_loadReloc;
loadsection: @elf_mips_loadSection;
+ encodeflags: nil;
);
initialization
# 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)
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
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
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)
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)
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)
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)
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,
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;
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
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
(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
{ 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
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}
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
statements : tstatementnode;
converted_result_data : ttempcreatenode;
calltype: tdispcalltype;
- label
- errorexit;
begin
result:=nil;
candidates:=nil;
oldcallnode:=aktcallnode;
aktcallnode:=self;
- { determine length of parameter list }
- pt:=tcallparanode(left);
- paralength:=0;
- while assigned(pt) do
- begin
- inc(paralength);
- pt:=tcallparanode(pt.right);
- end;
+ try
+ { determine length of parameter list }
+ pt:=tcallparanode(left);
+ paralength:=0;
+ while assigned(pt) do
+ begin
+ inc(paralength);
+ pt:=tcallparanode(pt.right);
+ end;
- { determine the type of the parameters }
- if assigned(left) then
- begin
- tcallparanode(left).get_paratype;
- if codegenerror then
- goto errorexit;
- end;
+ { determine the type of the parameters }
+ if assigned(left) then
+ begin
+ tcallparanode(left).get_paratype;
+ if codegenerror then
+ exit;
+ end;
- if assigned(methodpointer) then
- typecheckpass(methodpointer);
+ if assigned(methodpointer) then
+ typecheckpass(methodpointer);
- { procedure variable ? }
- if assigned(right) then
- begin
- set_varstate(right,vs_read,[vsf_must_be_valid]);
- typecheckpass(right);
- if codegenerror then
- exit;
+ { procedure variable ? }
+ if assigned(right) then
+ begin
+ set_varstate(right,vs_read,[vsf_must_be_valid]);
+ typecheckpass(right);
+ if codegenerror then
+ exit;
- procdefinition:=tabstractprocdef(right.resultdef);
+ procdefinition:=tabstractprocdef(right.resultdef);
- { Compare parameters from right to left }
- paraidx:=procdefinition.Paras.count-1;
- { Skip default parameters }
- if not(po_varargs in procdefinition.procoptions) then
- begin
- { ignore hidden parameters }
- while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
- dec(paraidx);
- for i:=1 to procdefinition.maxparacount-paralength do
- begin
- if paraidx<0 then
- internalerror(200402265);
- if not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym) then
- begin
- CGMessage1(parser_e_wrong_parameter_size,'<Procedure Variable>');
- goto errorexit;
- end;
+ { Compare parameters from right to left }
+ paraidx:=procdefinition.Paras.count-1;
+ { Skip default parameters }
+ if not(po_varargs in procdefinition.procoptions) then
+ begin
+ { ignore hidden parameters }
+ while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
dec(paraidx);
- end;
- end;
- while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
- dec(paraidx);
- pt:=tcallparanode(left);
- lastpara:=paralength;
- while (paraidx>=0) and assigned(pt) do
- begin
- { only goto next para if we're out of the varargs }
- if not(po_varargs in procdefinition.procoptions) or
- (lastpara<=procdefinition.maxparacount) then
- begin
- repeat
- dec(paraidx);
- until (paraidx<0) or not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions);
- end;
- pt:=tcallparanode(pt.right);
- dec(lastpara);
- end;
- if assigned(pt) or
- ((paraidx>=0) and
- not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym)) then
- begin
- if assigned(pt) then
- current_filepos:=pt.fileinfo;
- CGMessage1(parser_e_wrong_parameter_size,'<Procedure Variable>');
- goto errorexit;
- end;
- end
- else
- { not a procedure variable }
- begin
- { do we know the procedure to call ? }
- if not(assigned(procdefinition)) then
- begin
- { ignore possible private for properties or in delphi mode for anon. inherited (FK) }
- ignorevisibility:=(nf_isproperty in flags) or
- ((m_delphi in current_settings.modeswitches) and (cnf_anon_inherited in callnodeflags));
- candidates:=tcallcandidates.create(symtableprocentry,symtableproc,left,ignorevisibility,
- not(nf_isproperty in flags),cnf_objc_id_call in callnodeflags,cnf_unit_specified in callnodeflags,
- callnodeflags*[cnf_anon_inherited,cnf_inherited]=[],cnf_anon_inherited in callnodeflags);
-
- { no procedures found? then there is something wrong
- with the parameter size or the procedures are
- not accessible }
- if candidates.count=0 then
- begin
- { when it's an auto inherited call and there
- is no procedure found, but the procedures
- were defined with overload directive and at
- least two procedures are defined then we ignore
- this inherited by inserting a nothingn. Only
- do this ugly hack in Delphi mode as it looks more
- like a bug. It's also not documented }
- if (m_delphi in current_settings.modeswitches) and
- (cnf_anon_inherited in callnodeflags) and
- (symtableprocentry.owner.symtabletype=ObjectSymtable) and
- (po_overload in tprocdef(symtableprocentry.ProcdefList[0]).procoptions) and
- (symtableprocentry.ProcdefList.Count>=2) then
- result:=cnothingnode.create
- else
- begin
- { in tp mode we can try to convert to procvar if
- there are no parameters specified }
- if not(assigned(left)) and
- not(cnf_inherited in callnodeflags) and
- ((m_tp_procvar in current_settings.modeswitches) or
- (m_mac_procvar in current_settings.modeswitches)) and
- (not assigned(methodpointer) or
- (methodpointer.nodetype <> typen)) then
- begin
- hpt:=cloadnode.create(tprocsym(symtableprocentry),symtableproc);
- if assigned(methodpointer) then
- tloadnode(hpt).set_mp(methodpointer.getcopy);
- typecheckpass(hpt);
- result:=hpt;
- end
- else
- begin
- CGMessagePos1(fileinfo,parser_e_wrong_parameter_size,symtableprocentry.realname);
- symtableprocentry.write_parameter_lists(nil);
- end;
- end;
- candidates.free;
- goto errorexit;
- end;
+ for i:=1 to procdefinition.maxparacount-paralength do
+ begin
+ if paraidx<0 then
+ internalerror(200402265);
+ if not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym) then
+ begin
+ CGMessage1(parser_e_wrong_parameter_size,'<Procedure Variable>');
+ exit;
+ end;
+ dec(paraidx);
+ end;
+ end;
+ while (paraidx>=0) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
+ dec(paraidx);
+ pt:=tcallparanode(left);
+ lastpara:=paralength;
+ while (paraidx>=0) and assigned(pt) do
+ begin
+ { only goto next para if we're out of the varargs }
+ if not(po_varargs in procdefinition.procoptions) or
+ (lastpara<=procdefinition.maxparacount) then
+ begin
+ repeat
+ dec(paraidx);
+ until (paraidx<0) or not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions);
+ end;
+ pt:=tcallparanode(pt.right);
+ dec(lastpara);
+ end;
+ if assigned(pt) or
+ ((paraidx>=0) and
+ not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym)) then
+ begin
+ if assigned(pt) then
+ current_filepos:=pt.fileinfo;
+ CGMessage1(parser_e_wrong_parameter_size,'<Procedure Variable>');
+ exit;
+ end;
+ end
+ else
+ { not a procedure variable }
+ begin
+ { do we know the procedure to call ? }
+ if not(assigned(procdefinition)) then
+ begin
+ { ignore possible private for properties or in delphi mode for anon. inherited (FK) }
+ ignorevisibility:=(nf_isproperty in flags) or
+ ((m_delphi in current_settings.modeswitches) and (cnf_anon_inherited in callnodeflags));
+ candidates:=tcallcandidates.create(symtableprocentry,symtableproc,left,ignorevisibility,
+ not(nf_isproperty in flags),cnf_objc_id_call in callnodeflags,cnf_unit_specified in callnodeflags,
+ callnodeflags*[cnf_anon_inherited,cnf_inherited]=[],cnf_anon_inherited in callnodeflags);
+
+ { no procedures found? then there is something wrong
+ with the parameter size or the procedures are
+ not accessible }
+ if candidates.count=0 then
+ begin
+ { when it's an auto inherited call and there
+ is no procedure found, but the procedures
+ were defined with overload directive and at
+ least two procedures are defined then we ignore
+ this inherited by inserting a nothingn. Only
+ do this ugly hack in Delphi mode as it looks more
+ like a bug. It's also not documented }
+ if (m_delphi in current_settings.modeswitches) and
+ (cnf_anon_inherited in callnodeflags) and
+ (symtableprocentry.owner.symtabletype=ObjectSymtable) and
+ (po_overload in tprocdef(symtableprocentry.ProcdefList[0]).procoptions) and
+ (symtableprocentry.ProcdefList.Count>=2) then
+ result:=cnothingnode.create
+ else
+ begin
+ { in tp mode we can try to convert to procvar if
+ there are no parameters specified }
+ if not(assigned(left)) and
+ not(cnf_inherited in callnodeflags) and
+ ((m_tp_procvar in current_settings.modeswitches) or
+ (m_mac_procvar in current_settings.modeswitches)) and
+ (not assigned(methodpointer) or
+ (methodpointer.nodetype <> typen)) then
+ begin
+ hpt:=cloadnode.create(tprocsym(symtableprocentry),symtableproc);
+ if assigned(methodpointer) then
+ tloadnode(hpt).set_mp(methodpointer.getcopy);
+ typecheckpass(hpt);
+ result:=hpt;
+ end
+ else
+ begin
+ CGMessagePos1(fileinfo,parser_e_wrong_parameter_size,symtableprocentry.realname);
+ symtableprocentry.write_parameter_lists(nil);
+ end;
+ end;
+ candidates.free;
+ exit;
+ end;
- { Retrieve information about the candidates }
- candidates.get_information;
+ { Retrieve information about the candidates }
+ candidates.get_information;
{$ifdef EXTDEBUG}
- { Display info when multiple candidates are found }
- if candidates.count>1 then
- candidates.dump_info(V_Debug);
+ { Display info when multiple candidates are found }
+ if candidates.count>1 then
+ candidates.dump_info(V_Debug);
{$endif EXTDEBUG}
- { Choose the best candidate and count the number of
- candidates left }
- cand_cnt:=candidates.choose_best(procdefinition,
- assigned(left) and
- not assigned(tcallparanode(left).right) and
- (tcallparanode(left).left.resultdef.typ=variantdef));
+ { Choose the best candidate and count the number of
+ candidates left }
+ cand_cnt:=candidates.choose_best(procdefinition,
+ assigned(left) and
+ not assigned(tcallparanode(left).right) and
+ (tcallparanode(left).left.resultdef.typ=variantdef));
- { All parameters are checked, check if there are any
- procedures left }
- if cand_cnt>0 then
- begin
- { Multiple candidates left? }
- if cand_cnt>1 then
- begin
- CGMessage(type_e_cant_choose_overload_function);
+ { All parameters are checked, check if there are any
+ procedures left }
+ if cand_cnt>0 then
+ begin
+ { Multiple candidates left? }
+ if cand_cnt>1 then
+ begin
+ CGMessage(type_e_cant_choose_overload_function);
{$ifdef EXTDEBUG}
- candidates.dump_info(V_Hint);
+ candidates.dump_info(V_Hint);
{$else EXTDEBUG}
- candidates.list(false);
+ candidates.list(false);
{$endif EXTDEBUG}
- { we'll just use the first candidate to make the
- call }
- end;
+ { we'll just use the first candidate to make the
+ call }
+ end;
- { assign procdefinition }
- if symtableproc=nil then
- symtableproc:=procdefinition.owner;
- end
- else
- begin
- { No candidates left, this must be a type error,
- because wrong size is already checked. procdefinition
- is filled with the first (random) definition that is
- found. We use this definition to display a nice error
- message that the wrong type is passed }
- candidates.find_wrong_para;
- candidates.list(true);
+ { assign procdefinition }
+ if symtableproc=nil then
+ symtableproc:=procdefinition.owner;
+ end
+ else
+ begin
+ { No candidates left, this must be a type error,
+ because wrong size is already checked. procdefinition
+ is filled with the first (random) definition that is
+ found. We use this definition to display a nice error
+ message that the wrong type is passed }
+ candidates.find_wrong_para;
+ candidates.list(true);
{$ifdef EXTDEBUG}
- candidates.dump_info(V_Hint);
+ candidates.dump_info(V_Hint);
{$endif EXTDEBUG}
- { We can not proceed, release all procs and exit }
- candidates.free;
- goto errorexit;
- end;
+ { We can not proceed, release all procs and exit }
+ candidates.free;
+ exit;
+ end;
- candidates.free;
- end; { end of procedure to call determination }
- end;
+ candidates.free;
+ end; { end of procedure to call determination }
+ end;
- { check for hints (deprecated etc) }
- if procdefinition.typ = procdef then
- check_hints(tprocdef(procdefinition).procsym,tprocdef(procdefinition).symoptions,tprocdef(procdefinition).deprecatedmsg);
+ { check for hints (deprecated etc) }
+ if procdefinition.typ = procdef then
+ check_hints(tprocdef(procdefinition).procsym,tprocdef(procdefinition).symoptions,tprocdef(procdefinition).deprecatedmsg);
- { add reference to corresponding procsym; may not be the one
- originally found/passed to the constructor because of overloads }
- if procdefinition.typ = procdef then
- addsymref(tprocdef(procdefinition).procsym);
+ { add reference to corresponding procsym; may not be the one
+ originally found/passed to the constructor because of overloads }
+ if procdefinition.typ = procdef then
+ addsymref(tprocdef(procdefinition).procsym);
- { add needed default parameters }
- if (paralength<procdefinition.maxparacount) then
- begin
- paraidx:=0;
- i:=0;
- while (i<paralength) do
- begin
- if paraidx>=procdefinition.Paras.count then
- internalerror(200306181);
- if not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) then
- inc(i);
- inc(paraidx);
- end;
- while (paraidx<procdefinition.paras.count) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
- inc(paraidx);
- while (paraidx<procdefinition.paras.count) do
- begin
- if not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym) then
- internalerror(200212142);
- left:=ccallparanode.create(genconstsymtree(
- tconstsym(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym)),left);
- { Ignore vs_hidden parameters }
- repeat
+ { add needed default parameters }
+ if (paralength<procdefinition.maxparacount) then
+ begin
+ paraidx:=0;
+ i:=0;
+ while (i<paralength) do
+ begin
+ if paraidx>=procdefinition.Paras.count then
+ internalerror(200306181);
+ if not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) then
+ inc(i);
inc(paraidx);
- until (paraidx>=procdefinition.paras.count) or
- not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions);
- end;
- end;
+ end;
+ while (paraidx<procdefinition.paras.count) and (vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions) do
+ inc(paraidx);
+ while (paraidx<procdefinition.paras.count) do
+ begin
+ if not assigned(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym) then
+ internalerror(200212142);
+ left:=ccallparanode.create(genconstsymtree(
+ tconstsym(tparavarsym(procdefinition.paras[paraidx]).defaultconstsym)),left);
+ { Ignore vs_hidden parameters }
+ repeat
+ inc(paraidx);
+ until (paraidx>=procdefinition.paras.count) or
+ not(vo_is_hidden_para in tparavarsym(procdefinition.paras[paraidx]).varoptions);
+ end;
+ end;
- { recursive call? }
- if assigned(current_procinfo) and
- (procdefinition=current_procinfo.procdef) then
- include(current_procinfo.flags,pi_is_recursive);
-
- { handle predefined procedures }
- is_const:=(po_internconst in procdefinition.procoptions) and
- ((block_type in [bt_const,bt_type,bt_const_type,bt_var_type]) or
- (assigned(left) and ((tcallparanode(left).left.nodetype in [realconstn,ordconstn])
- and (not assigned(tcallparanode(left).right) or (tcallparanode(left).right.nodetype in [realconstn,ordconstn])))));
- if (procdefinition.proccalloption=pocall_internproc) or is_const then
- begin
- if assigned(left) then
- begin
- { convert types to those of the prototype, this is required by functions like ror, rol, sar
- some use however a dummy type (Typedfile) so this would break them }
- if not(tprocdef(procdefinition).extnumber in [fpc_in_Reset_TypedFile,fpc_in_Rewrite_TypedFile]) then
- begin
- { bind parasyms to the callparanodes and insert hidden parameters }
- bind_parasym;
+ { recursive call? }
+ if assigned(current_procinfo) and
+ (procdefinition=current_procinfo.procdef) then
+ include(current_procinfo.flags,pi_is_recursive);
+
+ { handle predefined procedures }
+ is_const:=(po_internconst in procdefinition.procoptions) and
+ ((block_type in [bt_const,bt_type,bt_const_type,bt_var_type]) or
+ (assigned(left) and ((tcallparanode(left).left.nodetype in [realconstn,ordconstn])
+ and (not assigned(tcallparanode(left).right) or (tcallparanode(left).right.nodetype in [realconstn,ordconstn])))));
+ if (procdefinition.proccalloption=pocall_internproc) or is_const then
+ begin
+ if assigned(left) then
+ begin
+ { convert types to those of the prototype, this is required by functions like ror, rol, sar
+ some use however a dummy type (Typedfile) so this would break them }
+ if not(tprocdef(procdefinition).extnumber in [fpc_in_Reset_TypedFile,fpc_in_Rewrite_TypedFile]) then
+ begin
+ { bind parasyms to the callparanodes and insert hidden parameters }
+ bind_parasym;
- { insert type conversions for parameters }
- if assigned(left) then
- tcallparanode(left).insert_typeconv;
- end;
+ { insert type conversions for parameters }
+ if assigned(left) then
+ tcallparanode(left).insert_typeconv;
+ end;
- { ptr and settextbuf need two args }
- if assigned(tcallparanode(left).right) then
- begin
- hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,left);
- left:=nil;
- end
- else
- begin
- hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,tcallparanode(left).left);
- tcallparanode(left).left:=nil;
- end;
- end
- else
- hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,nil);
- result:=hpt;
- goto errorexit;
- end;
+ { ptr and settextbuf need two args }
+ if assigned(tcallparanode(left).right) then
+ begin
+ hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,left);
+ left:=nil;
+ end
+ else
+ begin
+ hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,tcallparanode(left).left);
+ tcallparanode(left).left:=nil;
+ end;
+ end
+ else
+ hpt:=geninlinenode(tprocdef(procdefinition).extnumber,is_const,nil);
+ result:=hpt;
+ exit;
+ end;
- { ensure that the result type is set }
- if not(cnf_typedefset in callnodeflags) then
- begin
- { constructors return their current class type, not the type where the
- constructor is declared, this can be different because of inheritance }
- if (procdefinition.proctypeoption=potype_constructor) and
- assigned(methodpointer) and
- assigned(methodpointer.resultdef) and
- (methodpointer.resultdef.typ=classrefdef) then
- resultdef:=tclassrefdef(methodpointer.resultdef).pointeddef
- else
- { Member call to a (inherited) constructor from the class, the return
- value is always self, so we change it to voidtype to generate an
- error and to prevent users from generating non-working code
- when they expect to clone the current instance, see bug 3662 (PFV) }
+ { ensure that the result type is set }
+ if not(cnf_typedefset in callnodeflags) then
+ begin
+ { constructors return their current class type, not the type where the
+ constructor is declared, this can be different because of inheritance }
if (procdefinition.proctypeoption=potype_constructor) and
- is_class(tprocdef(procdefinition).struct) and
assigned(methodpointer) and
- (methodpointer.nodetype=loadn) and
- (loadnf_is_self in tloadnode(methodpointer).loadnodeflags) then
- resultdef:=voidtype
+ assigned(methodpointer.resultdef) and
+ (methodpointer.resultdef.typ=classrefdef) then
+ resultdef:=tclassrefdef(methodpointer.resultdef).pointeddef
else
- resultdef:=procdefinition.returndef;
- end
- else
- resultdef:=typedef;
-
- { Check object/class for methods }
- if assigned(methodpointer) then
- begin
- { direct call to inherited abstract method, then we
- can already give a error in the compiler instead
- of a runtime error }
- if (cnf_inherited in callnodeflags) and
- (po_abstractmethod in procdefinition.procoptions) then
- begin
- if (m_delphi in current_settings.modeswitches) and
- (cnf_anon_inherited in callnodeflags) then
- begin
- CGMessage(cg_h_inherited_ignored);
- result:=cnothingnode.create;
- exit;
- end
+ { Member call to a (inherited) constructor from the class, the return
+ value is always self, so we change it to voidtype to generate an
+ error and to prevent users from generating non-working code
+ when they expect to clone the current instance, see bug 3662 (PFV) }
+ if (procdefinition.proctypeoption=potype_constructor) and
+ is_class(tprocdef(procdefinition).struct) and
+ assigned(methodpointer) and
+ (methodpointer.nodetype=loadn) and
+ (loadnf_is_self in tloadnode(methodpointer).loadnodeflags) then
+ resultdef:=voidtype
else
- CGMessage(cg_e_cant_call_abstract_method);
- end;
+ resultdef:=procdefinition.returndef;
+ end
+ else
+ resultdef:=typedef;
- { directly calling an interface/protocol/category/class helper
- method via its type is not possible (always must be called via
- the actual instance) }
- if (methodpointer.nodetype=typen) and
- (is_interface(methodpointer.resultdef) or
- is_objc_protocol_or_category(methodpointer.resultdef)) then
- CGMessage1(type_e_class_type_expected,methodpointer.resultdef.typename);
-
- { if an inherited con- or destructor should be }
- { called in a con- or destructor then a warning }
- { will be made }
- { con- and destructors need a pointer to the vmt }
- if (cnf_inherited in callnodeflags) and
- (procdefinition.proctypeoption in [potype_constructor,potype_destructor]) and
- is_object(methodpointer.resultdef) and
- not(current_procinfo.procdef.proctypeoption in [potype_constructor,potype_destructor]) then
- CGMessage(cg_w_member_cd_call_from_method);
-
- if methodpointer.nodetype<>typen then
- begin
- { Remove all postfix operators }
- hpt:=methodpointer;
- while assigned(hpt) and (hpt.nodetype in [subscriptn,vecn]) do
- hpt:=tunarynode(hpt).left;
-
- if ((hpt.nodetype=loadvmtaddrn) or
- ((hpt.nodetype=loadn) and assigned(tloadnode(hpt).resultdef) and (tloadnode(hpt).resultdef.typ=classrefdef))) and
- not (procdefinition.proctypeoption=potype_constructor) and
- not (po_classmethod in procdefinition.procoptions) and
- not (po_staticmethod in procdefinition.procoptions) then
- { error: we are calling instance method from the class method/static method }
- CGMessage(parser_e_only_class_members);
-
- if (procdefinition.proctypeoption=potype_constructor) and
- assigned(symtableproc) and
- (symtableproc.symtabletype=withsymtable) and
- (tnode(twithsymtable(symtableproc).withrefnode).nodetype=temprefn) then
- CGmessage(cg_e_cannot_call_cons_dest_inside_with);
-
- { skip (absolute and other simple) type conversions -- only now,
- because the checks above have to take type conversions into
- e.g. class reference types account }
- hpt:=actualtargetnode(@hpt)^;
-
- { R.Init then R will be initialized by the constructor,
- Also allow it for simple loads }
- if (procdefinition.proctypeoption=potype_constructor) or
- ((hpt.nodetype=loadn) and
- (((methodpointer.resultdef.typ=objectdef) and
- not(oo_has_virtual in tobjectdef(methodpointer.resultdef).objectoptions)) or
- (methodpointer.resultdef.typ=recorddef)
- )
- ) then
- { a constructor will and a method may write something to }
- { the fields }
- set_varstate(methodpointer,vs_readwritten,[])
- else
- set_varstate(methodpointer,vs_read,[vsf_must_be_valid]);
- end;
+ { Check object/class for methods }
+ if assigned(methodpointer) then
+ begin
+ { direct call to inherited abstract method, then we
+ can already give a error in the compiler instead
+ of a runtime error }
+ if (cnf_inherited in callnodeflags) and
+ (po_abstractmethod in procdefinition.procoptions) then
+ begin
+ if (m_delphi in current_settings.modeswitches) and
+ (cnf_anon_inherited in callnodeflags) then
+ begin
+ CGMessage(cg_h_inherited_ignored);
+ result:=cnothingnode.create;
+ exit;
+ end
+ else
+ CGMessage(cg_e_cant_call_abstract_method);
+ end;
- { if we are calling the constructor check for abstract
- methods. Ignore inherited and member calls, because the
- class is then already created }
- if (procdefinition.proctypeoption=potype_constructor) and
- not(cnf_inherited in callnodeflags) and
- not(cnf_member_call in callnodeflags) then
- verifyabstractcalls;
- end
- else
- begin
- { When this is method the methodpointer must be available }
- if (right=nil) and
- (procdefinition.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
- not procdefinition.no_self_node then
- internalerror(200305061);
- end;
+ { directly calling an interface/protocol/category/class helper
+ method via its type is not possible (always must be called via
+ the actual instance) }
+ if (methodpointer.nodetype=typen) and
+ (is_interface(methodpointer.resultdef) or
+ is_objc_protocol_or_category(methodpointer.resultdef)) then
+ CGMessage1(type_e_class_type_expected,methodpointer.resultdef.typename);
+
+ { if an inherited con- or destructor should be }
+ { called in a con- or destructor then a warning }
+ { will be made }
+ { con- and destructors need a pointer to the vmt }
+ if (cnf_inherited in callnodeflags) and
+ (procdefinition.proctypeoption in [potype_constructor,potype_destructor]) and
+ is_object(methodpointer.resultdef) and
+ not(current_procinfo.procdef.proctypeoption in [potype_constructor,potype_destructor]) then
+ CGMessage(cg_w_member_cd_call_from_method);
+
+ if methodpointer.nodetype<>typen then
+ begin
+ { Remove all postfix operators }
+ hpt:=methodpointer;
+ while assigned(hpt) and (hpt.nodetype in [subscriptn,vecn]) do
+ hpt:=tunarynode(hpt).left;
+
+ if ((hpt.nodetype=loadvmtaddrn) or
+ ((hpt.nodetype=loadn) and assigned(tloadnode(hpt).resultdef) and (tloadnode(hpt).resultdef.typ=classrefdef))) and
+ not (procdefinition.proctypeoption=potype_constructor) and
+ not (po_classmethod in procdefinition.procoptions) and
+ not (po_staticmethod in procdefinition.procoptions) then
+ { error: we are calling instance method from the class method/static method }
+ CGMessage(parser_e_only_class_members);
+
+ if (procdefinition.proctypeoption=potype_constructor) and
+ assigned(symtableproc) and
+ (symtableproc.symtabletype=withsymtable) and
+ (tnode(twithsymtable(symtableproc).withrefnode).nodetype=temprefn) then
+ CGmessage(cg_e_cannot_call_cons_dest_inside_with);
+
+ { skip (absolute and other simple) type conversions -- only now,
+ because the checks above have to take type conversions into
+ e.g. class reference types account }
+ hpt:=actualtargetnode(@hpt)^;
+
+ { R.Init then R will be initialized by the constructor,
+ Also allow it for simple loads }
+ if (procdefinition.proctypeoption=potype_constructor) or
+ ((hpt.nodetype=loadn) and
+ (((methodpointer.resultdef.typ=objectdef) and
+ not(oo_has_virtual in tobjectdef(methodpointer.resultdef).objectoptions)) or
+ (methodpointer.resultdef.typ=recorddef)
+ )
+ ) then
+ { a constructor will and a method may write something to }
+ { the fields }
+ set_varstate(methodpointer,vs_readwritten,[])
+ else
+ set_varstate(methodpointer,vs_read,[vsf_must_be_valid]);
+ end;
- { Set flag that the procedure uses varargs, also if they are not passed it is still
- needed for x86_64 to pass the number of SSE registers used }
- if po_varargs in procdefinition.procoptions then
- include(callnodeflags,cnf_uses_varargs);
+ { if we are calling the constructor check for abstract
+ methods. Ignore inherited and member calls, because the
+ class is then already created }
+ if (procdefinition.proctypeoption=potype_constructor) and
+ not(cnf_inherited in callnodeflags) and
+ not(cnf_member_call in callnodeflags) then
+ verifyabstractcalls;
+ end
+ else
+ begin
+ { When this is method the methodpointer must be available }
+ if (right=nil) and
+ (procdefinition.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
+ not procdefinition.no_self_node then
+ internalerror(200305061);
+ end;
- { set the appropriate node flag if the call never returns }
- if po_noreturn in procdefinition.procoptions then
- include(callnodeflags,cnf_call_never_returns);
+ { Set flag that the procedure uses varargs, also if they are not passed it is still
+ needed for x86_64 to pass the number of SSE registers used }
+ if po_varargs in procdefinition.procoptions then
+ include(callnodeflags,cnf_uses_varargs);
- { Change loading of array of const to varargs }
- if assigned(left) and
- is_array_of_const(tparavarsym(procdefinition.paras[procdefinition.paras.count-1]).vardef) and
- (procdefinition.proccalloption in cdecl_pocalls) then
- convert_carg_array_of_const;
+ { set the appropriate node flag if the call never returns }
+ if po_noreturn in procdefinition.procoptions then
+ include(callnodeflags,cnf_call_never_returns);
- { bind parasyms to the callparanodes and insert hidden parameters }
- bind_parasym;
+ { Change loading of array of const to varargs }
+ if assigned(left) and
+ is_array_of_const(tparavarsym(procdefinition.paras[procdefinition.paras.count-1]).vardef) and
+ (procdefinition.proccalloption in cdecl_pocalls) then
+ convert_carg_array_of_const;
- { insert type conversions for parameters }
- if assigned(left) then
- tcallparanode(left).insert_typeconv;
+ { bind parasyms to the callparanodes and insert hidden parameters }
+ bind_parasym;
- { dispinterface methode invoke? }
- if assigned(methodpointer) and is_dispinterface(methodpointer.resultdef) then
- begin
- case procdefinition.proctypeoption of
- potype_propgetter: calltype:=dct_propget;
- potype_propsetter: calltype:=dct_propput;
- else
- calltype:=dct_method;
- end;
- { if the result is used, we've to insert a call to convert the type to be on the "safe side" }
- if (cnf_return_value_used in callnodeflags) and not is_void(procdefinition.returndef) then
- begin
- result:=internalstatements(statements);
- converted_result_data:=ctempcreatenode.create(procdefinition.returndef,sizeof(procdefinition.returndef),
- tt_persistent,true);
- addstatement(statements,converted_result_data);
- addstatement(statements,cassignmentnode.create(ctemprefnode.create(converted_result_data),
- ctypeconvnode.create_internal(
- translate_disp_call(methodpointer,parameters,calltype,'',tprocdef(procdefinition).dispid,procdefinition.returndef),
- procdefinition.returndef)));
- addstatement(statements,ctempdeletenode.create_normal_temp(converted_result_data));
- addstatement(statements,ctemprefnode.create(converted_result_data));
- end
- else
- result:=translate_disp_call(methodpointer,parameters,calltype,'',tprocdef(procdefinition).dispid,voidtype);
+ { insert type conversions for parameters }
+ if assigned(left) then
+ tcallparanode(left).insert_typeconv;
- { don't free reused nodes }
- methodpointer:=nil;
- parameters:=nil;
- end;
+ { dispinterface methode invoke? }
+ if assigned(methodpointer) and is_dispinterface(methodpointer.resultdef) then
+ begin
+ case procdefinition.proctypeoption of
+ potype_propgetter: calltype:=dct_propget;
+ potype_propsetter: calltype:=dct_propput;
+ else
+ calltype:=dct_method;
+ end;
+ { if the result is used, we've to insert a call to convert the type to be on the "safe side" }
+ if (cnf_return_value_used in callnodeflags) and not is_void(procdefinition.returndef) then
+ begin
+ result:=internalstatements(statements);
+ converted_result_data:=ctempcreatenode.create(procdefinition.returndef,sizeof(procdefinition.returndef),
+ tt_persistent,true);
+ addstatement(statements,converted_result_data);
+ addstatement(statements,cassignmentnode.create(ctemprefnode.create(converted_result_data),
+ ctypeconvnode.create_internal(
+ translate_disp_call(methodpointer,parameters,calltype,'',tprocdef(procdefinition).dispid,procdefinition.returndef),
+ procdefinition.returndef)));
+ addstatement(statements,ctempdeletenode.create_normal_temp(converted_result_data));
+ addstatement(statements,ctemprefnode.create(converted_result_data));
+ end
+ else
+ result:=translate_disp_call(methodpointer,parameters,calltype,'',tprocdef(procdefinition).dispid,voidtype);
- errorexit:
- aktcallnode:=oldcallnode;
+ { don't free reused nodes }
+ methodpointer:=nil;
+ parameters:=nil;
+ end;
+
+ finally
+ aktcallnode:=oldcallnode;
+ end;
end;
var
para: tcallparanode;
+ oldcallnode: tcallnode;
begin
result:=nil;
- { as pass_1 is never called on the methodpointer node, we must check
- here that it's not a helper type }
- if assigned(methodpointer) and
- (methodpointer.nodetype=typen) and
- is_objectpascal_helper(ttypenode(methodpointer).typedef) and
- not ttypenode(methodpointer).helperallowed then
- Message(parser_e_no_category_as_types);
-
- { can we get rid of the call? }
- if (cs_opt_remove_emtpy_proc in current_settings.optimizerswitches) and
- not(cnf_return_value_used in callnodeflags) and
- (procdefinition.typ=procdef) and
- tprocdef(procdefinition).isempty and
- { allow only certain proc options }
- ((tprocdef(procdefinition).procoptions-[po_none,po_classmethod,po_staticmethod,
- po_interrupt,po_iocheck,po_assembler,po_msgstr,po_msgint,po_exports,po_external,po_overload,
- po_nostackframe,po_has_mangledname,po_has_public_name,po_forward,po_global,
- po_inline,po_compilerproc,po_has_importdll,po_has_importname,po_kylixlocal,po_dispid,po_delphi_nested_cc,
- po_rtlproc,po_ignore_for_overload_resolution,po_auto_raised_visibility])=[]) then
- begin
- { check parameters for side effects }
- para:=tcallparanode(left);
- while assigned(para) do
- begin
- if (para.parasym.typ = paravarsym) and
- ((para.parasym.refs>0) or
- { array of consts are converted later on so we need to skip them here
- else no error detection is done }
- is_array_of_const(para.parasym.vardef) or
- not(cs_opt_dead_values in current_settings.optimizerswitches) or
- might_have_sideeffects(para.left)) then
- break;
- para:=tcallparanode(para.right);
- end;
- { finally, remove it if no parameter with side effect has been found }
- if para=nil then
- begin
- result:=cnothingnode.create;
- exit;
- end;
- end;
-
- { convert Objective-C calls into a message call }
- if (procdefinition.typ=procdef) and
- (po_objc in tprocdef(procdefinition).procoptions) then
- begin
- if not(cnf_objc_processed in callnodeflags) then
- objc_convert_to_message_send;
- end
- else
- begin
- { The following don't apply to obj-c: obj-c methods can never be
- inlined because they're always virtual and the destination can
- change at run, and for the same reason we also can't perform
- WPO on them (+ they have no constructors) }
+ oldcallnode:=aktcallnode;
+ aktcallnode:=self;
- { Check if the call can be inlined, sets the cnf_do_inline flag }
- check_inlining;
+ try
+ { as pass_1 is never called on the methodpointer node, we must check
+ here that it's not a helper type }
+ if assigned(methodpointer) and
+ (methodpointer.nodetype=typen) and
+ is_objectpascal_helper(ttypenode(methodpointer).typedef) and
+ not ttypenode(methodpointer).helperallowed then
+ Message(parser_e_no_category_as_types);
+
+ { can we get rid of the call? }
+ if (cs_opt_remove_emtpy_proc in current_settings.optimizerswitches) and
+ not(cnf_return_value_used in callnodeflags) and
+ (procdefinition.typ=procdef) and
+ tprocdef(procdefinition).isempty and
+ { allow only certain proc options }
+ ((tprocdef(procdefinition).procoptions-[po_none,po_classmethod,po_staticmethod,
+ po_interrupt,po_iocheck,po_assembler,po_msgstr,po_msgint,po_exports,po_external,po_overload,
+ po_nostackframe,po_has_mangledname,po_has_public_name,po_forward,po_global,
+ po_inline,po_compilerproc,po_has_importdll,po_has_importname,po_kylixlocal,po_dispid,po_delphi_nested_cc,
+ po_rtlproc,po_ignore_for_overload_resolution,po_auto_raised_visibility])=[]) then
+ begin
+ { check parameters for side effects }
+ para:=tcallparanode(left);
+ while assigned(para) do
+ begin
+ if (para.parasym.typ = paravarsym) and
+ ((para.parasym.refs>0) or
+ { array of consts are converted later on so we need to skip them here
+ else no error detection is done }
+ is_array_of_const(para.parasym.vardef) or
+ not(cs_opt_dead_values in current_settings.optimizerswitches) or
+ might_have_sideeffects(para.left)) then
+ break;
+ para:=tcallparanode(para.right);
+ end;
+ { finally, remove it if no parameter with side effect has been found }
+ if para=nil then
+ begin
+ result:=cnothingnode.create;
+ exit;
+ end;
+ end;
- { must be called before maybe_load_in_temp(methodpointer), because
- it converts the methodpointer into a temp in case it's a call
- (and we want to know the original call)
- }
- register_created_object_types;
- end;
+ { convert Objective-C calls into a message call }
+ if (procdefinition.typ=procdef) and
+ (po_objc in tprocdef(procdefinition).procoptions) then
+ begin
+ if not(cnf_objc_processed in callnodeflags) then
+ objc_convert_to_message_send;
+ end
+ else
+ begin
+ { The following don't apply to obj-c: obj-c methods can never be
+ inlined because they're always virtual and the destination can
+ change at run, and for the same reason we also can't perform
+ WPO on them (+ they have no constructors) }
+
+ { Check if the call can be inlined, sets the cnf_do_inline flag }
+ check_inlining;
+
+ { must be called before maybe_load_in_temp(methodpointer), because
+ it converts the methodpointer into a temp in case it's a call
+ (and we want to know the original call)
+ }
+ register_created_object_types;
+ end;
- { Maybe optimize the loading of the methodpointer using a temp. When the methodpointer
- is a calln this is even required to not execute the calln twice.
- This needs to be done after the resulttype pass, because in the resulttype we can still convert the
- calln to a loadn (PFV) }
- if assigned(methodpointer) then
- maybe_load_in_temp(methodpointer);
+ { Maybe optimize the loading of the methodpointer using a temp. When the methodpointer
+ is a calln this is even required to not execute the calln twice.
+ This needs to be done after the resulttype pass, because in the resulttype we can still convert the
+ calln to a loadn (PFV) }
+ if assigned(methodpointer) then
+ maybe_load_in_temp(methodpointer);
- { Create destination (temp or assignment-variable reuse) for function result if it not yet set }
- maybe_create_funcret_node;
+ { Create destination (temp or assignment-variable reuse) for function result if it not yet set }
+ maybe_create_funcret_node;
- { Insert the self,vmt,function result in the parameters }
- gen_hidden_parameters;
+ { Insert the self,vmt,function result in the parameters }
+ gen_hidden_parameters;
- { Remove useless nodes from init/final blocks }
- { (simplify depends on typecheck info) }
- if assigned(callinitblock) then
- begin
- typecheckpass(tnode(callinitblock));
- doinlinesimplify(tnode(callinitblock));
- end;
- if assigned(callcleanupblock) then
- begin
- typecheckpass(tnode(callcleanupblock));
- doinlinesimplify(tnode(callcleanupblock));
- end;
+ { Remove useless nodes from init/final blocks }
+ { (simplify depends on typecheck info) }
+ if assigned(callinitblock) then
+ begin
+ typecheckpass(tnode(callinitblock));
+ doinlinesimplify(tnode(callinitblock));
+ end;
+ if assigned(callcleanupblock) then
+ begin
+ typecheckpass(tnode(callcleanupblock));
+ doinlinesimplify(tnode(callcleanupblock));
+ end;
- { If a constructor calls another constructor of the same or of an
- inherited class, some targets (jvm) have to generate different
- entry code for the constructor. }
- if (current_procinfo.procdef.proctypeoption=potype_constructor) and
- (procdefinition.typ=procdef) and
- (tprocdef(procdefinition).proctypeoption=potype_constructor) and
- ([cnf_member_call,cnf_inherited] * callnodeflags <> []) then
- current_procinfo.ConstructorCallingConstructor:=true;
-
- { object check helper will load VMT -> needs GOT }
- if (cs_check_object in current_settings.localswitches) and
- (cs_create_pic in current_settings.moduleswitches) then
- include(current_procinfo.flags,pi_needs_got);
-
- { Continue with checking a normal call or generate the inlined code }
- if cnf_do_inline in callnodeflags then
- result:=pass1_inline
- else
- begin
- mark_unregable_parameters;
- result:=pass1_normal;
- end;
+ { If a constructor calls another constructor of the same or of an
+ inherited class, some targets (jvm) have to generate different
+ entry code for the constructor. }
+ if (current_procinfo.procdef.proctypeoption=potype_constructor) and
+ (procdefinition.typ=procdef) and
+ (tprocdef(procdefinition).proctypeoption=potype_constructor) and
+ ([cnf_member_call,cnf_inherited] * callnodeflags <> []) then
+ current_procinfo.ConstructorCallingConstructor:=true;
+
+ { object check helper will load VMT -> needs GOT }
+ if (cs_check_object in current_settings.localswitches) and
+ (cs_create_pic in current_settings.moduleswitches) then
+ include(current_procinfo.flags,pi_needs_got);
+
+ { Continue with checking a normal call or generate the inlined code }
+ if cnf_do_inline in callnodeflags then
+ result:=pass1_inline
+ else
+ begin
+ mark_unregable_parameters;
+ result:=pass1_normal;
+ end;
+ finally
+ aktcallnode:=oldcallnode;
+ end;
end;
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 }
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;
(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
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 }
{$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
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 }
interface
uses
- globtype,cgbase,cpuinfo,cpubase,
+ globtype,cgbase,cgutils,cpuinfo,cpubase,
+ symtype,
node,nmem;
type
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;
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
;
}
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
{ 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
{ 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;
{$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
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);
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;
end;
+ function tcgvecnode.valid_index_size(size: tcgsize): boolean;
+ begin
+ result:=
+ tcgsize2signed[size]=tcgsize2signed[OS_ADDR];
+ end;
+
+
procedure tcgvecnode.rangecheck_array;
var
hightree : tnode;
paraloc2 : tcgpara;
subsetref : tsubsetreference;
temp : longint;
+ indexdef : tdef;
begin
paraloc1.init;
paraloc2.init;
{ 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
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
{ 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 }
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;
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
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
{ 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;
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);
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,
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}
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
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
{ 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
((resultdef.typ=enumdef) and
(left.resultdef.typ=objectdef))) or
{$endif}
+ (
+ is_void(left.resultdef) and
+ (left.nodetype=derefn)
+ ) or
(
not(is_open_array(left.resultdef)) and
not(is_array_constructor(left.resultdef)) and
{ 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)
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
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 }
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 }
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;
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
TLOADPARENTFPNODE
*****************************************************************************}
- constructor tloadparentfpnode.create(pd:tprocdef);
+ constructor tloadparentfpnode.create(pd: tprocdef; fpkind: tloadparentfpkind);
begin
inherited create(loadparentfpn,nil);
if not assigned(pd) then
if (pd.parast.symtablelevel>current_procinfo.procdef.parast.symtablelevel) then
internalerror(200309284);
parentpd:=pd;
+ kind:=fpkind;
end;
begin
inherited ppuload(t,ppufile);
ppufile.getderef(parentpdderef);
+ kind:=tloadparentfpkind(ppufile.getbyte);
end;
begin
inherited ppuwrite(ppufile);
ppufile.putderef(parentpdderef);
+ ppufile.putbyte(byte(kind));
end;
begin
result:=
inherited docompare(p) and
- (tloadparentfpnode(p).parentpd=parentpd);
+ (tloadparentfpnode(p).parentpd=parentpd) and
+ (tloadparentfpnode(p).kind=kind);
end;
begin
p:=tloadparentfpnode(inherited dogetcopy);
p.parentpd:=parentpd;
+ p.kind:=kind;
dogetcopy:=p;
end;
end;
- { Used by PowerPC/64, ARM, and x86_64 }
+ { Used by PowerPC/64, ARM, x86_64 and AArch64 }
tobjcrttiwriter_nonfragile = class(tobjcrttiwriter)
protected
ObjCEmptyCacheVar,
{ 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);
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;
{$endif i386}
{$ifdef arm}
RELOC_RELATIVE_24,
+ RELOC_RELATIVE_24_THUMB,
+ RELOC_RELATIVE_CALL_THUMB,
{$endif arm}
{ Relative relocation }
RELOC_RELATIVE,
{ 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);
public
CurrPass : byte;
ExecStack : boolean;
+{$ifdef ARM}
+ ThumbFunc : boolean;
+{$endif ARM}
constructor create(const n:string);virtual;
destructor destroy;override;
{ Sections }
FCachedAsmSymbolList:=TFPObjectList.Create(false);
{ section class type for creating of new sections }
FCObjSection:=TObjSection;
+{$ifdef ARM}
+ ThumbFunc:=false;
+{$endif ARM}
end;
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;
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;
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}
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 }
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
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;
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 :
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 :
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
asmbin : '';
asmcmd : '';
supported_targets : [system_arm_wince];
- flags : [af_outputbinary];
+ flags : [af_outputbinary,af_smartlink_sections];
labelprefix : '.L';
comment : '';
dollarsign: '$';
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,
encodereloc: TEncodeRelocProc;
loadreloc: TLoadRelocProc;
loadsection: TLoadSectionProc;
+ encodeflags: TEncodeFlagsProc;
end;
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
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 }
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);
{$ifdef i8086}
'8',
{$endif}
+{$ifdef aarch64}
+ 'a',
+{$endif}
{$ifdef arm}
'A',
{$endif}
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
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;
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
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;
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;
{ 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');
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
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
{$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)}
{$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}
{ 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 ? }
{ 12 } 16 {'avr'},
{ 13 } 32 {'mipsel'},
{ 14 } 32 {'jvm'},
- { 15 } 16 {'i8086'}
+ { 15 } 16 {'i8086'},
+ { 16 } 64 {'aarch64'}
);
CpuAluBitSize : array[tsystemcpu] of longint =
(
{ 12 } 8 {'avr'},
{ 13 } 32 {'mipsel'},
{ 14 } 64 {'jvm'},
- { 15 } 16 {'i8086'}
+ { 15 } 16 {'i8086'},
+ { 16 } 64 {'aarch64'}
);
{$endif generic_cpu}
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 }
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);
// 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;
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
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
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;
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
{$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:
;
encodereloc: @elf_sparc_encodeReloc;
loadreloc: @elf_sparc_loadReloc;
loadsection: nil;
+ encodeflags: nil;
);
as_sparc_elf32_info : tasminfo =
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,
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';
{$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}
cpu_avr, { 12 }
cpu_mipsel, { 13 }
cpu_jvm, { 14 }
- cpu_i8086 { 15 }
+ cpu_i8086, { 15 }
+ cpu_aarch64 { 16 }
);
tasmmode= (asmmode_none
,asmmode_avr_gas
,asmmode_i8086_intel
,asmmode_i8086_att
+ ,asmmode_arm_gas_unified
);
(* IMPORTANT NOTE:
system_mipsel_embedded, { 82 }
system_i386_aros, { 83 }
system_x86_64_aros, { 84 }
- system_x86_64_dragonfly { 85 }
+ system_x86_64_dragonfly, { 85 }
+ system_aarch64_darwin, { 86 }
+ system_x86_64_iphonesim, { 87 }
+ system_aarch64_linux { 88 }
);
type
,as_i8086_nasm
,as_i8086_nasmobj
,as_gas_powerpc_xcoff
+ ,as_arm_elf32
,as_clang
);
,abi_powerpc_sysv,abi_powerpc_aix
,abi_eabi,abi_armeb,abi_eabihf
,abi_old_win32_gnu
+ ,abi_aarch64_darwin
);
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];
{ 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,
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,
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)
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),
(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
{$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;
);
+ 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;
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;
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
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.
{$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;
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);
Cprefix : '';
newline : #13#10;
dirsep : '\';
- assem : as_gas;
+ assem : as_arm_pecoffwince;
assemextern : as_gas;
link : ld_int_windows;
linkextern : ld_windows;
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
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;
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
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);
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);
{$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}
{$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}
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
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);
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;
#
[target]
-programs=fpc ppufiles ppudump ppumove mkarmins mkx86ins
+programs=fpc ppufiles ppudump ppumove mka64ins mkarmins mkx86ins
rst=fpcsubst
[clean]
ppcbin:='ppcarm';
processorname:='arm';
{$endif arm}
+{$ifdef aarch64}
+ ppcbin:='ppca64';
+ processorname:='aarch64';
+{$endif arm}
{$ifdef sparc}
ppcbin:='ppcsparc';
processorname:='sparc';
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'
**********************************************************************}
{$mode objfpc}
-program mkarmins;
+program mka64ins;
const
Version = '0.9';
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;
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;
optypes[2]:='';
optypes[3]:='';
optypes[4]:='';
+ optypes[5]:='';
+ optypes[6]:='';
codes:='';
flags:='';
skip:=false;
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;
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,' )');
{ 12 } 'avr',
{ 13 } 'mipsel',
{ 14 } 'jvm',
- { 15 } 'i8086'
+ { 15 } 'i8086',
+ { 16 } 'aarch64'
);
{ List of all supported system-cpu couples }
{ 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',
{ 43 } 'Linux-powerpc64',
{ 44 } 'Darwin-i386',
{ 45 } 'PalmOS-arm',
- { 46 } 'MacOSX-powerpc64',
+ { 46 } 'Darwin-powerpc64',
{ 47 } 'NDS-arm',
{ 48 } 'Embedded-i386',
{ 49 } 'Embedded-m68k',
{ 58 } 'Embedded-powerpc64',
{ 59 } 'Symbian-i386',
{ 60 } 'Symbian-arm',
- { 61 } 'MacOSX-x64',
+ { 61 } 'Darwin-x64',
{ 62 } 'Embedded-avr',
{ 63 } 'Haiku-i386',
{ 64 } 'Darwin-ARM',
{ 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
{$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;
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 : '# ';
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 : '# ';
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;
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
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);
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
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 ****************}
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;
{ 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;
uses
globtype,
cgbase,cpuinfo,cpubase,
+ symtype,
node,nmem,ncgmem;
type
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
{ 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;
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;
encodereloc: @elf_x86_64_encodeReloc;
loadreloc: @elf_x86_64_loadReloc;
loadsection: nil;
+ encodeflags: nil;
);
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
type
TElfMachineType = (emtnone, emtsparc, emti386, emtm68k, emtppc, emtppc64,
emtarm, emtarmeb, emtia64, emtx86_64, emtalpha,
- emtmips, emtmipsel);
+ emtmips, emtmipsel, emtaarch64);
const
ELFMAGIC = chr($7f)+'ELF';
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
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;
fMachineType:=emtarmeb;
{$ENDIF}
{$ENDIF}
+ {$IFDEF CPUAARCH64}
+ fMachineType:=emtaarch64;
+ {$ENDIF}
{$IFDEF CPU68K}
fMachineType:=emtm68k;
{$ENDIF}
fMachineType:=emtarm
else
fMachineType:=emtarmeb;
+ EM_AARCH64: fMachineType:=emtaarch64;
EM_ALPHA : fMachineType:=emtalpha;
EM_IA_64 : fMachineType:=emtia64;
EM_X86_64 : fMachineType:=emtx86_64;
_TElfRelocTable_= class
private
fList : TFPList;
- fRelocType : byte;
+ fRelocType : longword;
fEntrySize : integer;
fSectionType : integer;
fSectionName : string;
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;
type
TElfRelocInfo = record
- RelocType : byte;
+ RelocType : longword;
SectionType : integer;
end;
(*
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;
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;
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
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;
// relocation types - ARM
ARM_RELOC_VANILLA = 0; // generic relocation
+ // relocation types - AARCH64
+ ARM64_RELOC_UNSIGNED = 0; // for pointers
+
implementation
end.
{$IFDEF CPUARM}
fMachineType:=mmtarm;
{$ENDIF}
+ {$IFDEF CPUAARCH64}
+ fMachineType:=mmtarm64;
+ {$ENDIF}
fBits:=MACH_ERRBIT;
{$IFDEF CPU32}
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;
_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)
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;
{ _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;
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);
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_);
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);
procedure _TMachOSubWriter_.WriteNodeInfos(aStream: TStream);
begin
+ { offset inside the object }
fCurOfs:=sizeof(_TResHdr_);
WriteNodeInfo(aStream,fRoot);
WriteSubNodes(aStream,fRoot);
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
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);
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
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;
ressection.reserved1:=0;
ressection.reserved2:=0;
+ fillbyte(bsssection,sizeof(bsssection),0);
bsssection.sectname:=HandlesSectName;
bsssection.segname:=DataSegName;
bsssection.addr:=fDataCurOfs;
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));
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
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
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;
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;
flags : longword;
end;
- TSegmentCommand64 = packed record
+ TSegmentCommand64 = record
name : TSegSectName;
vmaddr : qword;
vmsize : qword;
flags : longword;
end;
- TSection32 = packed record
+ TSection32 = record
sectname : TSegSectName;
segname : TSegSectName;
addr : longword;
reserved2 : longword;
end;
- TSection64 = packed record
+ TSection64 = record
sectname : TSegSectName;
segname : TSegSectName;
addr : qword;
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;
nlocrel : longword;
end;
- TNList32 = packed record
+ TNList32 = record
strx : longword;
_type : byte;
sect : byte;
end;
PNList32 = ^TNList32;
- TNList64 = packed record
+ TNList64 = record
strx : longword;
_type : byte;
sect : byte;
end;
PNList64 = ^TNList64;
- TRelocationInfo = packed record
+ TRelocationInfo = record
address : longword;
flags : longword;
end;
type
EMachOResourceWriterException = class(EResourceWriterException);
EMachOResourceWriterUnknownBitSizeException = class(EMachOResourceWriterException);
+ EMachOResourceWriterSymbolTableWrongOrderException = class(EMachOResourceWriterException);
type
msm386_all: (f386SubType: TMachOSubMachineType386);
msmx64_all: (fX64SubType: TMachOSubMachineTypex64);
mmtarm: (fArmSubType: TMachOSubMachineTypeArm);
+ mmtarm64: (fArm64SubType: TMachOSubMachineTypeAarch64);
end;
TMachOResourceWriter = class(TAbstractResourceWriter)
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;
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;
fCurOfs : longword;
fDataCurOfs : longword;
fSectionStart : longword;
+ ffpcresourcessym,
+ ffpcreshandlessym : integer;
function NextAligned(aBound, aValue : longword) : longword;
procedure Align(aBound : integer; aStream : TStream);
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;
fRelocType:=ARM_RELOC_VANILLA;
fRelocSize:=2;
end;
+ mmtarm64 : begin
+ fEndianess:=MACH_LITTLE_ENDIAN;
+ fRelocType:=ARM64_RELOC_UNSIGNED;
+ fRelocSize:=3;
+ end;
end;
fOppositeEndianess:=aOppositeEndianess;
end;
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));
//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;
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
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;
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;
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;
// 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;
{ 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
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
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;
version=3.0.4
[target]
-units=iosxlocale
+units=iosxlocale iosxwstr
[libs]
libversion=2.0.0
P.OSes:=[darwin,iphonesim];
T:=P.Targets.AddUnit('iosxlocale.pp');
+ T:=P.Targets.AddUnit('iosxwstr.pp');
{$ifndef ALLPACKAGES}
Run;
--- /dev/null
+{
+ 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.
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}
{$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}
--- /dev/null
+{
+
+ 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}
--- /dev/null
+{
+ 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 }
--- /dev/null
+#
+# Here we set processor dependent include file names.
+#
+
+CPUNAMES=aarch64 int64p math set setjump setjumph strings stringss
+CPUINCNAMES=$(addsuffix .inc,$(CPUNAMES))
+#
--- /dev/null
+{
+ 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}
+
+
--- /dev/null
+{
+ 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;
--- /dev/null
+{
+ 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.
+
+ **********************************************************************}
+
--- /dev/null
+{
+ 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;
+
+
--- /dev/null
+{
+ 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'];
+
--- /dev/null
+{
+ 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.
+
+ **********************************************************************}
+
--- /dev/null
+{
+ 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.
+
+ **********************************************************************}
+
+
**********************************************************************}
-{$asmmode gas}
-
{$ifndef FPC_SYSTEM_HAS_MOVE}
{$define FPC_SYSTEM_FPC_MOVE}
{$endif FPC_SYSTEM_HAS_MOVE}
**********************************************************************}
-{$asmmode gas}
+{$asmmode divided}
{$ifndef FPC_SYSTEM_HAS_MOVE}
{$define FPC_SYSTEM_FPC_MOVE}
{$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;
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
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}
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
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
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;
--- /dev/null
+
+{$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;
+
+
--- /dev/null
+{
+ 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;
+
{$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
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;
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;
{$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}
{$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;
{$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}
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
}
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;
{$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 !}
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;
{$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}
{$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}
{$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}
--- /dev/null
+{ nothing }
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ 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
--- /dev/null
+{
+ 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;
--- /dev/null
+{
+ 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;
--- /dev/null
+{
+ 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;
--- /dev/null
+{
+ 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;
--- /dev/null
+{
+ 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';
--- /dev/null
+{$i ../sysnr-gen.inc}
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;
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;
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}
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}
{$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;
{
}
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,
syscall_nr_lstat64,
{$endif}
TSysParam(path),TSysParam(info));
+{$endif}
end;
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
}
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'];
**********************************************************************}
unit Linux;
+{$i osdefs.inc}
+
{$packrecords c}
{$ifdef FPC_USE_LIBC}
{$linklib rt} // for clock* functions
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;
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;
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;
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;
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;
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;
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;
{$endif FPC_ABI_EABI}
{$endif cpuarm}
+{$ifdef cpuaarch64}
+ {$define generic_linux_syscalls}
+ {$undef usestime}
+{$endif cpuaarch64}
*****************************************************************************}
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;
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'];
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}
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'];
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}
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}
}
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);
}
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
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;
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;
{$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)}
--- /dev/null
+{
+ 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
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;
{$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;
__SIZEOF_PTHREAD_BARRIER_T = 20;
__SIZEOF_PTHREAD_BARRIERATTR_T = 4;
{$endif CPU32}
-{$endif MIPS}
+{$endif}
{$I ctypes.inc}
{$packrecords c}
__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}
--- /dev/null
+
+{
+ 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;
{ 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}
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;
threadvarblocksize:=align(threadvarblocksize,16);
{$endif cpupowerpc64}
+ {$ifdef cpuaarch64}
+ threadvarblocksize:=align(threadvarblocksize,16);
+ {$endif cpuaarch64}
+
offset:=threadvarblocksize;
inc(threadvarblocksize,size);
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
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=(
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=(
{ 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
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');
mtia64 : Result.MachineType:=emtia64;
mtmips : Result.MachineType:=emtmips;
mtmipsel : Result.MachineType:=emtmipsel;
+ mtaarch64 : Result.MachineType:=emtaarch64;
end;
end;
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;
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;
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;
(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
);
(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);
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;