/*
 * Test s390x-softmmu precise self-modifying code handling.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */
    .org 0x8e
program_interruption_code:
    .org 0x150
program_old_psw:
    .org 0x1D0                         /* program new PSW */
    .quad 0x180000000,pgm              /* 64-bit mode */
    .org 0x200                         /* lowcore padding */
    .globl _start
_start:
    lctlg %c0,%c0,c0
    lghi %r0,15

    /* Test 1: replace sgr with agr. */
    lghi %r1,21
    vl %v0,patch1
    jg 1f                              /* start a new TB */
0:
    .org . + 6                         /* pad patched code to 16 bytes */
1:
    vstl %v0,%r0,0b                    /* start writing before TB */
    sgr %r1,%r1                        /* this becomes `agr %r1,%r1` */
    cgijne %r1,42,failure

    /* Test 2: replace agr with division by zero. */
    vl %v0,patch2
    jg 1f                              /* start a new TB */
0:
    .org . + 6                         /* pad patched code to 16 bytes */
1:
    vstl %v0,%r0,0b                    /* start writing before TB */
    sgr %r1,%r1                        /* this becomes `d %r0,zero` */
failure:
    lpswe failure_psw

pgm:
    chhsi program_interruption_code,0x9          /* divide exception? */
    jne failure
    clc program_old_psw(16),expected_old_psw2    /* correct old PSW? */
    jne failure
    lpswe success_psw

patch1:
    .fill 12                           /* replaces padding and stpq */
    agr %r1,%r1                        /* replaces sgr */
patch2:
    .fill 12                           /* replaces padding and stpq */
    d %r0,zero                         /* replaces sgr */
zero:
    .long 0
expected_old_psw2:
    .quad 0x200180000000,failure       /* cc is from addition */
    .align 8
c0:
    .quad 0x60000                      /* AFP, VX */
success_psw:
    .quad 0x2000000000000,0xfff        /* see is_special_wait_psw() */
failure_psw:
    .quad 0x2000000000000,0            /* disabled wait */