// REQUIRES: aarch64
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o
// RUN: ld.lld -fix-cortex-a53-843419 -verbose -t %t.o -o /dev/null | FileCheck %s
// Test cases for Cortex-A53 Erratum 843419 that we don't expect to recognize
// as needing a patch as one or more of the conditions isn't satisfied.
// See ARM-EPM-048406 Cortex_A53_MPCore_Software_Developers_Errata_Notice.pdf
// for full erratum details.
// In Summary
// 1.)
// ADRP (0xff8 or 0xffc)
// 2.)
// - load or store single register or either integer or vector registers
// - STP or STNP of either vector or vector registers
// - Advanced SIMD ST1 store instruction
// Must not write Rn
// 3.) optional instruction, can't be a branch, must not write Rn, may read Rn
// 4.) A load or store instruction from the Load/Store register unsigned
// immediate class using Rn as the base register
// Expect no patches detected.
// CHECK-NOT: detected cortex-a53-843419 erratum sequence
// erratum sequence but adrp (address & 0xfff) is not 0xff8 or 0xffc
.section .text.01, "ax", %progbits
.balign 4096
.globl t3_0_ldr
.type t3_ff8_ldr, %function
t3_0_ldr:
adrp x0, dat
ldr x1, [x1, #0]
ldr x0, [x0, :got_lo12:dat]
ret
.section .text.02, "ax", %progbits
.balign 4096
.globl t3_ff4_ldr
.space 4096 - 12
.type t3_ff4_ldr, %function
t3_ff4_ldr:
adrp x0, dat
ldr x1, [x1, #0]
ldr x0, [x0, :got_lo12:dat]
ret
// Close matches for erratum sequence, with adrp at correct address but
// instruction 2 is a load or store but not one that matches the erratum
// conditions, but with a similar encoding to an instruction that does.
// ldp is not part of sequence, although stp is.
.section .text.03, "ax", %progbits
.balign 4096
.globl t3_ff8_ldp
.type t3_ff8_ldp, %function
.space 4096 - 8
t3_ff8_ldp:
adrp x16, dat
ldp x1,x2, [x3, #0]
ldr x13, [x16, :got_lo12:dat]
ret
// st2 is not part of sequence although st1 is.
.section .text.04, "ax", %progbits
.balign 4096
.globl t3_ffc_st2
.type t3_ffc_st2, %function
.space 4096 - 4
t3_ffc_st2:
adrp x16, dat
st2 { v0.16b, v1.16b }, [x1]
ldr x13, [x16, :got_lo12:dat]
ret
// st3 is not part of sequence although st1 is.
.section .text.05, "ax", %progbits
.balign 4096
.globl t3_ffc_st3
.type t3_ffc_st3, %function
.space 4096 - 4
t3_ffc_st3:
adrp x16, dat
st3 { v0.16b, v1.16b, v2.16b }, [x1], x2
ldr x13, [x16, :got_lo12:dat]
ret
// ld1 is not part of sequence although st1 is.
.section .text.06, "ax", %progbits
.balign 4096
.globl t3_ffc_ld2
.type t3_ffc_st3, %function
.space 4096 - 4
t3_ffc_ld1:
adrp x16, dat
ld1 { v0.16b }, [x2], x3
ldr x13, [x16, :got_lo12:dat]
ret
// ldnp is not part of sequence although stnp is.
.section .text.07, "ax", %progbits
.balign 4096
.globl t4_ff8_ldnp
.type t4_ff8_ldnp, %function
.space 4096 - 8
t4_ff8_ldnp:
adrp x7, dat
ldnp x1,x2, [x3, #0]
nop
ldr x10, [x7, :got_lo12:dat]
ret
// Close match for erratum sequence, with adrp at correct address but
// instruction 2 writes to Rn, with Rn as either destination or as the
// transfer register but with writeback.
// ldr instruction writes to Rn
.section .text.08, "ax", %progbits
.balign 4096
.globl t3_ff8_ldr
.type t3_ff8_ldr, %function
.space 4096 - 8
t3_ff8_ldr:
adrp x0, dat
ldr x0, [x1, #0]
ldr x0, [x0, :got_lo12:dat]
ret
// str instruction writes to Rn via writeback (pre index)
.section .text.09, "ax", %progbits
.balign 4096
.globl t3_ff8_str
.type t3_ff8_str, %function
.space 4096 - 8
t3_ff8_str:
adrp x0, dat
str x1, [x0, #4]!
ldr x0, [x0, :got_lo12:dat]
ret
// ldr instruction writes to Rn via writeback (post index)
.section .text.09, "ax", %progbits
.balign 4096
.globl t3_ffc_ldr
.type t3_ffc_ldr, %function
.space 4096 - 8
t3_ffc_ldr:
adrp x0, dat
ldr x1, [x0], 0x8
ldr x0, [x0, :got_lo12:dat]
ret
// stp writes to Rn via writeback (pre index)
.section .text.10, "ax", %progbits
.balign 4096
.globl t4_ffc_stppre
.type t4_ffc_stppre, %function
.space 4096 - 4
t4_ffc_stppre:
adrp x16, dat
stp x1,x2, [x16, #16]!
mul x3, x16, x16
ldr x14, [x16, #8]
ret
// stp writes to Rn via writeback (post index)
.section .text.11, "ax", %progbits
.balign 4096
.globl t4_ff8_stppost
.type t4_ff8_stppost, %function
.space 4096 - 8
t4_ff8_stppost:
adrp x16, dat
stp x1,x2, [x16], #16
mul x3, x16, x16
ldr x14, [x16, #8]
ret
// st1 writes to Rn via writeback
.section .text.12, "ax", %progbits
.balign 4096
.globl t3_ff8_st1
.type t3_ff8_st1, %function
.space 4096 - 8
t3_ff8_st1:
adrp x16, dat
st1 { v0.16b}, [x16], x2
ldr x13, [x16, :got_lo12:dat]
ret
// Close match for erratum sequence, but with optional instruction 3 a branch
// function call via immediate
.section .text.13, "ax", %progbits
.balign 4096
.globl t4_ffc_blimm
.type t4_ffc_blimm, %function
.space 4096 - 4
t4_ffc_blimm:
adrp x7, dat
stnp x1,x2, [x3, #0]
bl t4_ffc_blimm
ldr x10, [x7, :got_lo12:dat]
ret
// function call via register
.section .text.14, "ax", %progbits
.balign 4096
.globl t4_ffc_blreg
.type t4_ffc_blreg, %function
.space 4096 - 4
t4_ffc_blreg:
adrp x7, dat
stnp x1,x2, [x3, #0]
blr x4
ldr x10, [x7, :got_lo12:dat]
ret
// Unconditional branch immediate
.section .text.15, "ax", %progbits
.balign 4096
.globl t4_ffc_branchimm
.type t4_ffc_branchimm, %function
.space 4096 - 4
t4_ffc_branchimm:
adrp x7, dat
stnp x1,x2, [x3, #0]
b t4_ffc_branchimm
ldr x10, [x7, :got_lo12:dat]
ret
// Unconditional branch register
.section .text.16, "ax", %progbits
.balign 4096
.globl t4_ffc_branchreg
.type t4_ffc_branchreg, %function
.space 4096 - 4
t4_ffc_branchreg:
adrp x7, dat
stnp x1,x2, [x3, #0]
br x4
ldr x10, [x7, :got_lo12:dat]
ret
// Conditional branch
.section .text.17, "ax", %progbits
.balign 4096
.globl t4_ffc_branchcond
.type t4_ffc_branchcond, %function
.space 4096 - 4
t4_ffc_branchcond:
adrp x7, dat
stnp x1,x2, [x3, #0]
cbz x5, t4_ffc_branchcond
ldr x10, [x7, :got_lo12:dat]
ret
// Conditional branch immediate
.section .text.18, "ax", %progbits
.balign 4096
.globl t4_ffc_branchcondimm
.type t4_ffc_branchcondimm, %function
.space 4096 - 4
t4_ffc_branchcondimm:
adrp x7, dat
stnp x1,x2, [x3, #0]
beq t4_ffc_branchcondimm
ldr x10, [x7, :got_lo12:dat]
ret
// Bitpattern matches erratum sequence but either all or part of the sequence
// is in inline literal data
.section .text.19, "ax", %progbits
.balign 4096
.globl t3_ffc_ldrtraildata
.type t3_ff8_ldrtraildata, %function
.space 4096 - 8
t3_ff8_ldrtraildata:
adrp x0, dat
ldr x1, [x1, #0]
// 0xf9400000 = ldr x0, [x0]
.byte 0x00
.byte 0x00
.byte 0x40
.byte 0xf9
ldr x0, [x0, :got_lo12:dat]
ret
.section .text.20, "ax", %progbits
.balign 4096
.globl t3_ffc_ldrpredata
.type t3_ff8_ldrpredata, %function
.space 4096 - 8
t3_ff8_ldrpredata:
// 0x90000000 = adrp x0, #0
.byte 0x00
.byte 0x00
.byte 0x00
.byte 0x90
ldr x1, [x1, #0]
ldr x0, [x0, :got_lo12:dat]
ret
.section .text.21, "ax", %progbits
.balign 4096
.globl t3_ffc_ldralldata
.type t3_ff8_ldralldata, %function
.space 4096 - 8
t3_ff8_ldralldata:
// 0x90000000 = adrp x0, #0
.byte 0x00
.byte 0x00
.byte 0x00
.byte 0x90
// 0xf9400021 = ldr x1, [x1]
.byte 0x21
.byte 0x00
.byte 0x40
.byte 0xf9
// 0xf9400000 = ldr x0, [x0]
.byte 0x00
.byte 0x00
.byte 0x40
.byte 0xf9
ret
.text
.globl _start
.type _start, %function
_start:
ret
// Bitpattern matches erratum sequence but section is not executable
.data
.globl dat
dat: .word 0