qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 07/10] tcg: implement bulletproof JIT


From: Joelle van Dyne
Subject: Re: [PATCH 07/10] tcg: implement bulletproof JIT
Date: Wed, 14 Oct 2020 09:03:26 -0700

Hi Philippe,

Will work on splitting the patch for v2. Thanks for the tip on git.orderfile

Hi Balaton,

Reply inline.

-j


On Tue, Oct 13, 2020 at 7:58 AM BALATON Zoltan <balaton@eik.bme.hu> wrote:
>
> On Mon, 12 Oct 2020, Joelle van Dyne wrote:
> > From: osy <osy86@users.noreply.github.com>
> >
> > On iOS, we cannot allocate RWX pages without special entitlements. As a
> > workaround, we can a RX region and then mirror map it to a separate RX
>
> Missing a verb here: "we can a RX region"
Good catch.

>
> > region. Then we can write to one region and execute from the other one.
> >
> > To better keep track of pointers to RW/RX memory, we mark any tcg_insn_unit
> > pointers as `const` if they will never be written to. We also define a new
> > macro `TCG_CODE_PTR_RW` that returns a pointer to RW memory. Only the
> > difference between the two regions is stored in the TCG context.
>
> Maybe it's easier to review if constification is split off as separate
> patch before other changes.
Will do.

>
> > To ensure cache coherency, we flush the data cache in the RW mapping and
> > then invalidate the instruction cache in the RX mapping (where applicable).
> > Because data cache flush is OS defined on some architectures, we do not
> > provide implementations for non iOS platforms (ARM/x86).
> >
> > Signed-off-by: Joelle van Dyne <j@getutm.app>
> > ---
> > accel/tcg/cpu-exec.c         |  7 +++-
> > accel/tcg/translate-all.c    | 78 ++++++++++++++++++++++++++++++++++--
> > configure                    |  1 +
> > docs/devel/ios.rst           | 40 ++++++++++++++++++
> > include/exec/exec-all.h      |  8 ++++
> > include/tcg/tcg.h            | 18 +++++++--
> > tcg/aarch64/tcg-target.c.inc | 48 +++++++++++++---------
> > tcg/aarch64/tcg-target.h     | 13 +++++-
> > tcg/arm/tcg-target.c.inc     | 33 ++++++++-------
> > tcg/arm/tcg-target.h         |  9 ++++-
> > tcg/i386/tcg-target.c.inc    | 28 ++++++-------
> > tcg/i386/tcg-target.h        | 24 ++++++++++-
> > tcg/mips/tcg-target.c.inc    | 64 +++++++++++++++++------------
> > tcg/mips/tcg-target.h        |  8 +++-
> > tcg/ppc/tcg-target.c.inc     | 55 ++++++++++++++++---------
> > tcg/ppc/tcg-target.h         |  8 +++-
> > tcg/riscv/tcg-target.c.inc   | 51 +++++++++++++----------
> > tcg/riscv/tcg-target.h       |  9 ++++-
> > tcg/s390/tcg-target.c.inc    | 25 ++++++------
> > tcg/s390/tcg-target.h        | 13 +++++-
> > tcg/sparc/tcg-target.c.inc   | 33 +++++++++------
> > tcg/sparc/tcg-target.h       |  8 +++-
> > tcg/tcg-ldst.c.inc           |  2 +-
> > tcg/tcg-pool.c.inc           |  9 +++--
> > tcg/tcg.c                    | 60 +++++++++++++++++----------
> > tcg/tci/tcg-target.c.inc     |  8 ++--
> > tcg/tci/tcg-target.h         |  9 ++++-
> > 27 files changed, 481 insertions(+), 188 deletions(-)
> > create mode 100644 docs/devel/ios.rst
> >
> > diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
> > index 58aea605d8..821aefdea2 100644
> > --- a/accel/tcg/cpu-exec.c
> > +++ b/accel/tcg/cpu-exec.c
> > @@ -354,7 +354,12 @@ void tb_set_jmp_target(TranslationBlock *tb, int n, 
> > uintptr_t addr)
> >     if (TCG_TARGET_HAS_direct_jump) {
> >         uintptr_t offset = tb->jmp_target_arg[n];
> >         uintptr_t tc_ptr = (uintptr_t)tb->tc.ptr;
> > -        tb_target_set_jmp_target(tc_ptr, tc_ptr + offset, addr);
> > +#if defined(CONFIG_IOS_JIT)
> > +        uintptr_t wr_addr = tc_ptr + offset + tb->code_rw_mirror_diff;
> > +#else
> > +        uintptr_t wr_addr = tc_ptr + offset;
> > +#endif
> > +        tb_target_set_jmp_target(tc_ptr, tc_ptr + offset, addr, wr_addr);
> >     } else {
> >         tb->jmp_target_arg[n] = addr;
> >     }
> > diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
> > index d76097296d..76d8dc3d7b 100644
> > --- a/accel/tcg/translate-all.c
> > +++ b/accel/tcg/translate-all.c
> > @@ -60,6 +60,22 @@
> > #include "sysemu/cpu-timers.h"
> > #include "sysemu/tcg.h"
> >
> > +#if defined(CONFIG_IOS_JIT)
> > +#include <mach/mach.h>
> > +extern kern_return_t mach_vm_remap(vm_map_t target_task,
> > +                                   mach_vm_address_t *target_address,
> > +                                   mach_vm_size_t size,
> > +                                   mach_vm_offset_t mask,
> > +                                   int flags,
> > +                                   vm_map_t src_task,
> > +                                   mach_vm_address_t src_address,
> > +                                   boolean_t copy,
> > +                                   vm_prot_t *cur_protection,
> > +                                   vm_prot_t *max_protection,
> > +                                   vm_inherit_t inheritance
> > +                                  );
> > +#endif
> > +
> > /* #define DEBUG_TB_INVALIDATE */
> > /* #define DEBUG_TB_FLUSH */
> > /* make various TB consistency checks */
> > @@ -302,10 +318,13 @@ static target_long decode_sleb128(uint8_t **pp)
> >
> > static int encode_search(TranslationBlock *tb, uint8_t *block)
> > {
> > -    uint8_t *highwater = tcg_ctx->code_gen_highwater;
> > -    uint8_t *p = block;
> > +    uint8_t *highwater;
> > +    uint8_t *p;
> >     int i, j, n;
> >
> > +    highwater = (uint8_t *)TCG_CODE_PTR_RW(tcg_ctx,
> > +                                           tcg_ctx->code_gen_highwater);
> > +    p = (uint8_t *)TCG_CODE_PTR_RW(tcg_ctx, block);
>
> Why do you need explicit casts here? Can this be avoided by using
> appropriate type or within the macro (I haven't checked this at all just
> dislike casts as they can hide problems otherwise caught by the compiler).
There's the choice between tcg_insn_unit * and uint8_t *. Since it's
used much more widely in tcg-target.inc.c, it seemed like
tcg_insn_unit * was a better choice.

>
> Regards,
> BALATON Zoltan
>
> >     for (i = 0, n = tb->icount; i < n; ++i) {
> >         target_ulong prev;
> >
> > @@ -329,7 +348,7 @@ static int encode_search(TranslationBlock *tb, uint8_t 
> > *block)
> >         }
> >     }
> >
> > -    return p - block;
> > +    return p - (uint8_t *)TCG_CODE_PTR_RW(tcg_ctx, block);
> > }
> >
> > /* The cpu state corresponding to 'searched_pc' is restored.
> > @@ -1067,7 +1086,11 @@ static inline void *alloc_code_gen_buffer(void)
> > #else
> > static inline void *alloc_code_gen_buffer(void)
> > {
> > +#if defined(CONFIG_IOS_JIT)
> > +    int prot = PROT_READ | PROT_EXEC;
> > +#else
> >     int prot = PROT_WRITE | PROT_READ | PROT_EXEC;
> > +#endif
> >     int flags = MAP_PRIVATE | MAP_ANONYMOUS;
> >     size_t size = tcg_ctx->code_gen_buffer_size;
> >     void *buf;
> > @@ -1118,6 +1141,39 @@ static inline void *alloc_code_gen_buffer(void)
> > }
> > #endif /* USE_STATIC_CODE_GEN_BUFFER, WIN32, POSIX */
> >
> > +#if defined(CONFIG_IOS_JIT)
> > +static inline void *alloc_jit_rw_mirror(void *base, size_t size)
> > +{
> > +    kern_return_t ret;
> > +    mach_vm_address_t mirror;
> > +    vm_prot_t cur_prot, max_prot;
> > +
> > +    mirror = 0;
> > +    ret = mach_vm_remap(mach_task_self(),
> > +                        &mirror,
> > +                        size,
> > +                        0,
> > +                        VM_FLAGS_ANYWHERE | VM_FLAGS_RANDOM_ADDR,
> > +                        mach_task_self(),
> > +                        (mach_vm_address_t)base,
> > +                        false,
> > +                        &cur_prot,
> > +                        &max_prot,
> > +                        VM_INHERIT_NONE
> > +                       );
> > +    if (ret != KERN_SUCCESS) {
> > +        return NULL;
> > +    }
> > +
> > +    if (mprotect((void *)mirror, size, PROT_READ | PROT_WRITE) != 0) {
> > +        munmap((void *)mirror, size);
> > +        return NULL;
> > +    }
> > +
> > +    return (void *)mirror;
> > +}
> > +#endif /* CONFIG_IOS_JIT */
> > +
> > static inline void code_gen_alloc(size_t tb_size)
> > {
> >     tcg_ctx->code_gen_buffer_size = size_code_gen_buffer(tb_size);
> > @@ -1126,6 +1182,19 @@ static inline void code_gen_alloc(size_t tb_size)
> >         fprintf(stderr, "Could not allocate dynamic translator buffer\n");
> >         exit(1);
> >     }
> > +#if defined(CONFIG_IOS_JIT)
> > +    void *mirror;
> > +
> > +    /* For iOS JIT we need a mirror mapping for code execution */
> > +    mirror = alloc_jit_rw_mirror(tcg_ctx->code_gen_buffer,
> > +                                 tcg_ctx->code_gen_buffer_size
> > +                                );
> > +    if (mirror == NULL) {
> > +        fprintf(stderr, "Could not remap code buffer mirror\n");
> > +        exit(1);
> > +    }
> > +    tcg_ctx->code_rw_mirror_diff = mirror - tcg_ctx->code_gen_buffer;
> > +#endif /* CONFIG_IOS_JIT */
> > }
> >
> > static bool tb_cmp(const void *ap, const void *bp)
> > @@ -1721,6 +1790,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
> >         cpu_loop_exit(cpu);
> >     }
> >
> > +#if defined(CONFIG_IOS_JIT)
> > +    tb->code_rw_mirror_diff = tcg_ctx->code_rw_mirror_diff;
> > +#endif
> >     gen_code_buf = tcg_ctx->code_gen_ptr;
> >     tb->tc.ptr = gen_code_buf;
> >     tb->pc = pc;
> > diff --git a/configure b/configure
> > index 16c66b437c..c5a6584683 100755
> > --- a/configure
> > +++ b/configure
> > @@ -6220,6 +6220,7 @@ fi
> >
> > if test "$ios" = "yes" ; then
> >   echo "CONFIG_IOS=y" >> $config_host_mak
> > +  echo "CONFIG_IOS_JIT=y" >> $config_host_mak
> > fi
> >
> > if test "$solaris" = "yes" ; then
> > diff --git a/docs/devel/ios.rst b/docs/devel/ios.rst
> > new file mode 100644
> > index 0000000000..dba9fdd868
> > --- /dev/null
> > +++ b/docs/devel/ios.rst
> > @@ -0,0 +1,40 @@
> > +===========
> > +iOS Support
> > +===========
> > +
> > +To run qemu on the iOS platform, some modifications were required. Most of 
> > the
> > +modifications are conditioned on the ``CONFIG_IOS`` and ``CONFIG_IOS_JIT``
> > +configuration variables.
> > +
> > +Build support
> > +-------------
> > +
> > +For the code to compile, certain changes in the block driver and the slirp
> > +driver had to be made. There is no ``system()`` call, so code requiring it 
> > had
> > +to be disabled.
> > +
> > +``ucontext`` support is broken on iOS. The implementation from 
> > ``libucontext``
> > +is used instead.
> > +
> > +Because ``fork()`` is not allowed on iOS apps, the option to build qemu 
> > and the
> > +utilities as shared libraries is added. Note that because qemu does not 
> > perform
> > +resource cleanup in most cases (open files, allocated memory, etc), it is
> > +advisable that the user implements a proxy layer for syscalls so resources 
> > can
> > +be kept track by the app that uses qemu as a shared library.
> > +
> > +JIT support
> > +-----------
> > +
> > +On iOS, allocating RWX pages require special entitlements not usually 
> > granted to
> > +apps. However, it is possible to use `bulletproof JIT`_ with a development
> > +certificate. This means that we need to allocate one chunk of memory with 
> > RX
> > +permissions and then mirror map the same memory with RW permissions. We 
> > generate
> > +code to the mirror mapping and execute the original mapping.
> > +
> > +With ``CONFIG_IOS_JIT`` defined, we store inside the TCG context the 
> > difference
> > +between the two mappings. Then, we make sure that any writes to JIT memory 
> > is
> > +done to the pointer + the difference (in order to get a pointer to the 
> > mirror
> > +mapped space). Additionally, we make sure to flush the data cache before we
> > +invalidate the instruction cache so the changes are seen in both mappings.
> > +
> > +.. _bulletproof JIT: 
> > https://www.blackhat.com/docs/us-16/materials/us-16-Krstic.pdf
> > diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
> > index 66f9b4cca6..2db155a772 100644
> > --- a/include/exec/exec-all.h
> > +++ b/include/exec/exec-all.h
> > @@ -483,6 +483,14 @@ struct TranslationBlock {
> >     uintptr_t jmp_list_head;
> >     uintptr_t jmp_list_next[2];
> >     uintptr_t jmp_dest[2];
> > +
> > +#if defined(CONFIG_IOS_JIT)
> > +    /*
> > +     * Store difference to writable mirror
> > +     * We need this when patching the jump instructions
> > +     */
> > +    ptrdiff_t code_rw_mirror_diff;
> > +#endif
> > };
> >
> > extern bool parallel_cpus;
> > diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
> > index 8804a8c4a2..40d1a7a85e 100644
> > --- a/include/tcg/tcg.h
> > +++ b/include/tcg/tcg.h
> > @@ -261,7 +261,7 @@ struct TCGLabel {
> >     unsigned refs : 16;
> >     union {
> >         uintptr_t value;
> > -        tcg_insn_unit *value_ptr;
> > +        const tcg_insn_unit *value_ptr;
> >     } u;
> >     QSIMPLEQ_HEAD(, TCGRelocation) relocs;
> >     QSIMPLEQ_ENTRY(TCGLabel) next;
> > @@ -593,7 +593,7 @@ struct TCGContext {
> >     int nb_ops;
> >
> >     /* goto_tb support */
> > -    tcg_insn_unit *code_buf;
> > +    const tcg_insn_unit *code_buf;
> >     uint16_t *tb_jmp_reset_offset; /* tb->jmp_reset_offset */
> >     uintptr_t *tb_jmp_insn_offset; /* tb->jmp_target_arg if direct_jump */
> >     uintptr_t *tb_jmp_target_addr; /* tb->jmp_target_arg if !direct_jump */
> > @@ -627,6 +627,9 @@ struct TCGContext {
> >     size_t code_gen_buffer_size;
> >     void *code_gen_ptr;
> >     void *data_gen_ptr;
> > +#if defined(CONFIG_IOS_JIT)
> > +    ptrdiff_t code_rw_mirror_diff;
> > +#endif
> >
> >     /* Threshold to flush the translated code buffer.  */
> >     void *code_gen_highwater;
> > @@ -677,6 +680,13 @@ struct TCGContext {
> >     target_ulong gen_insn_data[TCG_MAX_INSNS][TARGET_INSN_START_WORDS];
> > };
> >
> > +#if defined(CONFIG_IOS_JIT)
> > +# define TCG_CODE_PTR_RW(s, code_ptr) \
> > +    (tcg_insn_unit *)((uintptr_t)(code_ptr) + (s)->code_rw_mirror_diff)
> > +#else
> > +# define TCG_CODE_PTR_RW(s, code_ptr) (code_ptr)
> > +#endif
> > +
> > extern TCGContext tcg_init_ctx;
> > extern __thread TCGContext *tcg_ctx;
> > extern TCGv_env cpu_env;
> > @@ -1099,7 +1109,7 @@ static inline TCGLabel *arg_label(TCGArg i)
> >  * correct result.
> >  */
> >
> > -static inline ptrdiff_t tcg_ptr_byte_diff(void *a, void *b)
> > +static inline ptrdiff_t tcg_ptr_byte_diff(const void *a, const void *b)
> > {
> >     return a - b;
> > }
> > @@ -1113,7 +1123,7 @@ static inline ptrdiff_t tcg_ptr_byte_diff(void *a, 
> > void *b)
> >  * to the destination address.
> >  */
> >
> > -static inline ptrdiff_t tcg_pcrel_diff(TCGContext *s, void *target)
> > +static inline ptrdiff_t tcg_pcrel_diff(TCGContext *s, const void *target)
> > {
> >     return tcg_ptr_byte_diff(target, s->code_ptr);
> > }
> > diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
> > index 26f71cb599..9cfa2703b3 100644
> > --- a/tcg/aarch64/tcg-target.c.inc
> > +++ b/tcg/aarch64/tcg-target.c.inc
> > @@ -78,38 +78,44 @@ static const int tcg_target_call_oarg_regs[1] = {
> > #define TCG_REG_GUEST_BASE TCG_REG_X28
> > #endif
> >
> > -static inline bool reloc_pc26(tcg_insn_unit *code_ptr, tcg_insn_unit 
> > *target)
> > +static inline bool reloc_pc26(TCGContext *s,
> > +                              tcg_insn_unit *code_ptr,
> > +                              const tcg_insn_unit *target)
> > {
> >     ptrdiff_t offset = target - code_ptr;
> >     if (offset == sextract64(offset, 0, 26)) {
> >         /* read instruction, mask away previous PC_REL26 parameter contents,
> >            set the proper offset, then write back the instruction. */
> > -        *code_ptr = deposit32(*code_ptr, 0, 26, offset);
> > +        *TCG_CODE_PTR_RW(s, code_ptr) =
> > +            deposit32(*TCG_CODE_PTR_RW(s, code_ptr), 0, 26, offset);
> >         return true;
> >     }
> >     return false;
> > }
> >
> > -static inline bool reloc_pc19(tcg_insn_unit *code_ptr, tcg_insn_unit 
> > *target)
> > +static inline bool reloc_pc19(TCGContext *s,
> > +                              tcg_insn_unit *code_ptr,
> > +                              const tcg_insn_unit *target)
> > {
> >     ptrdiff_t offset = target - code_ptr;
> >     if (offset == sextract64(offset, 0, 19)) {
> > -        *code_ptr = deposit32(*code_ptr, 5, 19, offset);
> > +        *TCG_CODE_PTR_RW(s, code_ptr) =
> > +            deposit32(*TCG_CODE_PTR_RW(s, code_ptr), 5, 19, offset);
> >         return true;
> >     }
> >     return false;
> > }
> >
> > -static inline bool patch_reloc(tcg_insn_unit *code_ptr, int type,
> > +static inline bool patch_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int 
> > type,
> >                                intptr_t value, intptr_t addend)
> > {
> >     tcg_debug_assert(addend == 0);
> >     switch (type) {
> >     case R_AARCH64_JUMP26:
> >     case R_AARCH64_CALL26:
> > -        return reloc_pc26(code_ptr, (tcg_insn_unit *)value);
> > +        return reloc_pc26(s, code_ptr, (tcg_insn_unit *)value);
> >     case R_AARCH64_CONDBR19:
> > -        return reloc_pc19(code_ptr, (tcg_insn_unit *)value);
> > +        return reloc_pc19(s, code_ptr, (tcg_insn_unit *)value);
> >     default:
> >         g_assert_not_reached();
> >     }
> > @@ -1306,14 +1312,14 @@ static void tcg_out_cmp(TCGContext *s, TCGType ext, 
> > TCGReg a,
> >     }
> > }
> >
> > -static inline void tcg_out_goto(TCGContext *s, tcg_insn_unit *target)
> > +static inline void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
> > {
> >     ptrdiff_t offset = target - s->code_ptr;
> >     tcg_debug_assert(offset == sextract64(offset, 0, 26));
> >     tcg_out_insn(s, 3206, B, offset);
> > }
> >
> > -static inline void tcg_out_goto_long(TCGContext *s, tcg_insn_unit *target)
> > +static inline void tcg_out_goto_long(TCGContext *s, const tcg_insn_unit 
> > *target)
> > {
> >     ptrdiff_t offset = target - s->code_ptr;
> >     if (offset == sextract64(offset, 0, 26)) {
> > @@ -1329,7 +1335,7 @@ static inline void tcg_out_callr(TCGContext *s, 
> > TCGReg reg)
> >     tcg_out_insn(s, 3207, BLR, reg);
> > }
> >
> > -static inline void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
> > +static inline void tcg_out_call(TCGContext *s, const tcg_insn_unit *target)
> > {
> >     ptrdiff_t offset = target - s->code_ptr;
> >     if (offset == sextract64(offset, 0, 26)) {
> > @@ -1341,7 +1347,7 @@ static inline void tcg_out_call(TCGContext *s, 
> > tcg_insn_unit *target)
> > }
> >
> > void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr,
> > -                              uintptr_t addr)
> > +                              uintptr_t addr, uintptr_t wr_addr)
> > {
> >     tcg_insn_unit i1, i2;
> >     TCGType rt = TCG_TYPE_I64;
> > @@ -1362,7 +1368,10 @@ void tb_target_set_jmp_target(uintptr_t tc_ptr, 
> > uintptr_t jmp_addr,
> >         i2 = I3401_ADDI | rt << 31 | (addr & 0xfff) << 10 | rd << 5 | rd;
> >     }
> >     pair = (uint64_t)i2 << 32 | i1;
> > -    qatomic_set((uint64_t *)jmp_addr, pair);
> > +    qatomic_set((uint64_t *)wr_addr, pair);
> > +#if defined(CONFIG_IOS_JIT)
> > +    flush_dcache_range(wr_addr, wr_addr + 8);
> > +#endif
> >     flush_icache_range(jmp_addr, jmp_addr + 8);
> > }
> >
> > @@ -1568,7 +1577,7 @@ static void * const qemu_st_helpers[16] = {
> >     [MO_BEQ]  = helper_be_stq_mmu,
> > };
> >
> > -static inline void tcg_out_adr(TCGContext *s, TCGReg rd, void *target)
> > +static inline void tcg_out_adr(TCGContext *s, TCGReg rd, const void 
> > *target)
> > {
> >     ptrdiff_t offset = tcg_pcrel_diff(s, target);
> >     tcg_debug_assert(offset == sextract64(offset, 0, 21));
> > @@ -1581,7 +1590,7 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *lb)
> >     MemOp opc = get_memop(oi);
> >     MemOp size = opc & MO_SIZE;
> >
> > -    if (!reloc_pc19(lb->label_ptr[0], s->code_ptr)) {
> > +    if (!reloc_pc19(s, lb->label_ptr[0], s->code_ptr)) {
> >         return false;
> >     }
> >
> > @@ -1606,7 +1615,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *lb)
> >     MemOp opc = get_memop(oi);
> >     MemOp size = opc & MO_SIZE;
> >
> > -    if (!reloc_pc19(lb->label_ptr[0], s->code_ptr)) {
> > +    if (!reloc_pc19(s, lb->label_ptr[0], s->code_ptr)) {
> >         return false;
> >     }
> >
> > @@ -1622,7 +1631,8 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *lb)
> >
> > static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
> >                                 TCGType ext, TCGReg data_reg, TCGReg 
> > addr_reg,
> > -                                tcg_insn_unit *raddr, tcg_insn_unit 
> > *label_ptr)
> > +                                const tcg_insn_unit *raddr,
> > +                                tcg_insn_unit *label_ptr)
> > {
> >     TCGLabelQemuLdst *label = new_ldst_label(s);
> >
> > @@ -1849,7 +1859,7 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg 
> > data_reg, TCGReg addr_reg,
> > #endif /* CONFIG_SOFTMMU */
> > }
> >
> > -static tcg_insn_unit *tb_ret_addr;
> > +static const tcg_insn_unit *tb_ret_addr;
> >
> > static void tcg_out_op(TCGContext *s, TCGOpcode opc,
> >                        const TCGArg args[TCG_MAX_OP_ARGS],
> > @@ -2916,11 +2926,11 @@ static void tcg_target_qemu_prologue(TCGContext *s)
> >     tcg_out_insn(s, 3207, RET, TCG_REG_LR);
> > }
> >
> > -static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
> > +static void tcg_out_nop_fill(TCGContext *s, tcg_insn_unit *p, int count)
> > {
> >     int i;
> >     for (i = 0; i < count; ++i) {
> > -        p[i] = NOP;
> > +        (TCG_CODE_PTR_RW(s, p))[i] = NOP;
> >     }
> > }
> >
> > diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
> > index a2b22b4305..78c97460a1 100644
> > --- a/tcg/aarch64/tcg-target.h
> > +++ b/tcg/aarch64/tcg-target.h
> > @@ -150,6 +150,7 @@ typedef enum {
> >
> > #if defined(__APPLE__)
> > void sys_icache_invalidate(void *start, size_t len);
> > +void sys_dcache_flush(void *start, size_t len);
> > #endif
> >
> > static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
> > @@ -163,7 +164,17 @@ static inline void flush_icache_range(uintptr_t start, 
> > uintptr_t stop)
> > #endif
> > }
> >
> > -void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
> > +void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
> > +#if defined(CONFIG_IOS_JIT)
> > +static inline void flush_dcache_range(uintptr_t start, uintptr_t stop)
> > +{
> > +#if defined(__APPLE__)
> > +    sys_dcache_flush((char *)start, stop - start);
> > +#else
> > +#error "Missing function to flush data cache"
> > +#endif
> > +}
> > +#endif
> >
> > #ifdef CONFIG_SOFTMMU
> > #define TCG_TARGET_NEED_LDST_LABELS
> > diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
> > index 62c37a954b..d27ad851b5 100644
> > --- a/tcg/arm/tcg-target.c.inc
> > +++ b/tcg/arm/tcg-target.c.inc
> > @@ -187,17 +187,22 @@ static const uint8_t tcg_cond_to_arm_cond[] = {
> >     [TCG_COND_GTU] = COND_HI,
> > };
> >
> > -static inline bool reloc_pc24(tcg_insn_unit *code_ptr, tcg_insn_unit 
> > *target)
> > +static inline bool reloc_pc24(TCGContext *s,
> > +                              tcg_insn_unit *code_ptr,
> > +                              const tcg_insn_unit *target)
> > {
> >     ptrdiff_t offset = (tcg_ptr_byte_diff(target, code_ptr) - 8) >> 2;
> >     if (offset == sextract32(offset, 0, 24)) {
> > -        *code_ptr = (*code_ptr & ~0xffffff) | (offset & 0xffffff);
> > +        *TCG_CODE_PTR_RW(s, code_ptr) =
> > +            (*TCG_CODE_PTR_RW(s, code_ptr) & ~0xffffff) | (offset & 
> > 0xffffff);
> >         return true;
> >     }
> >     return false;
> > }
> >
> > -static inline bool reloc_pc13(tcg_insn_unit *code_ptr, tcg_insn_unit 
> > *target)
> > +static inline bool reloc_pc13(TCGContext *s,
> > +                              tcg_insn_unit *code_ptr,
> > +                              const tcg_insn_unit *target)
> > {
> >     ptrdiff_t offset = tcg_ptr_byte_diff(target, code_ptr) - 8;
> >
> > @@ -209,21 +214,21 @@ static inline bool reloc_pc13(tcg_insn_unit 
> > *code_ptr, tcg_insn_unit *target)
> >         }
> >         insn = deposit32(insn, 23, 1, u);
> >         insn = deposit32(insn, 0, 12, offset);
> > -        *code_ptr = insn;
> > +        *TCG_CODE_PTR_RW(s, code_ptr) = insn;
> >         return true;
> >     }
> >     return false;
> > }
> >
> > -static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
> > +static bool patch_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type,
> >                         intptr_t value, intptr_t addend)
> > {
> >     tcg_debug_assert(addend == 0);
> >
> >     if (type == R_ARM_PC24) {
> > -        return reloc_pc24(code_ptr, (tcg_insn_unit *)value);
> > +        return reloc_pc24(s, code_ptr, (tcg_insn_unit *)value);
> >     } else if (type == R_ARM_PC13) {
> > -        return reloc_pc13(code_ptr, (tcg_insn_unit *)value);
> > +        return reloc_pc13(s, code_ptr, (tcg_insn_unit *)value);
> >     } else {
> >         g_assert_not_reached();
> >     }
> > @@ -1019,7 +1024,7 @@ static inline void tcg_out_st8(TCGContext *s, int 
> > cond,
> >  * with the code buffer limited to 16MB we wouldn't need the long case.
> >  * But we also use it for the tail-call to the qemu_ld/st helpers, which 
> > does.
> >  */
> > -static void tcg_out_goto(TCGContext *s, int cond, tcg_insn_unit *addr)
> > +static void tcg_out_goto(TCGContext *s, int cond, const tcg_insn_unit 
> > *addr)
> > {
> >     intptr_t addri = (intptr_t)addr;
> >     ptrdiff_t disp = tcg_pcrel_diff(s, addr);
> > @@ -1033,7 +1038,7 @@ static void tcg_out_goto(TCGContext *s, int cond, 
> > tcg_insn_unit *addr)
> >
> > /* The call case is mostly used for helpers - so it's not unreasonable
> >  * for them to be beyond branch range */
> > -static void tcg_out_call(TCGContext *s, tcg_insn_unit *addr)
> > +static void tcg_out_call(TCGContext *s, const tcg_insn_unit *addr)
> > {
> >     intptr_t addri = (intptr_t)addr;
> >     ptrdiff_t disp = tcg_pcrel_diff(s, addr);
> > @@ -1326,7 +1331,7 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg 
> > addrlo, TCGReg addrhi,
> >    helper code.  */
> > static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
> >                                 TCGReg datalo, TCGReg datahi, TCGReg addrlo,
> > -                                TCGReg addrhi, tcg_insn_unit *raddr,
> > +                                TCGReg addrhi, const tcg_insn_unit *raddr,
> >                                 tcg_insn_unit *label_ptr)
> > {
> >     TCGLabelQemuLdst *label = new_ldst_label(s);
> > @@ -1348,7 +1353,7 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *lb)
> >     MemOp opc = get_memop(oi);
> >     void *func;
> >
> > -    if (!reloc_pc24(lb->label_ptr[0], s->code_ptr)) {
> > +    if (!reloc_pc24(s, lb->label_ptr[0], s->code_ptr)) {
> >         return false;
> >     }
> >
> > @@ -1411,7 +1416,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *lb)
> >     TCGMemOpIdx oi = lb->oi;
> >     MemOp opc = get_memop(oi);
> >
> > -    if (!reloc_pc24(lb->label_ptr[0], s->code_ptr)) {
> > +    if (!reloc_pc24(s, lb->label_ptr[0], s->code_ptr)) {
> >         return false;
> >     }
> >
> > @@ -2255,11 +2260,11 @@ static inline void tcg_out_movi(TCGContext *s, 
> > TCGType type,
> >     tcg_out_movi32(s, COND_AL, ret, arg);
> > }
> >
> > -static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
> > +static void tcg_out_nop_fill(TCGContext *s, tcg_insn_unit *p, int count)
> > {
> >     int i;
> >     for (i = 0; i < count; ++i) {
> > -        p[i] = INSN_NOP;
> > +        (TCG_CODE_PTR_RW(s, p))[i] = INSN_NOP;
> >     }
> > }
> >
> > diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
> > index 17e771374d..d8d7e7e239 100644
> > --- a/tcg/arm/tcg-target.h
> > +++ b/tcg/arm/tcg-target.h
> > @@ -139,8 +139,15 @@ static inline void flush_icache_range(uintptr_t start, 
> > uintptr_t stop)
> >     __builtin___clear_cache((char *) start, (char *) stop);
> > }
> >
> > +#if defined(CONFIG_IOS_JIT)
> > +static inline void flush_dcache_range(uintptr_t start, uintptr_t stop)
> > +{
> > +#error "Unimplemented dcache flush function"
> > +}
> > +#endif
> > +
> > /* not defined -- call should be eliminated at compile time */
> > -void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
> > +void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
> >
> > #ifdef CONFIG_SOFTMMU
> > #define TCG_TARGET_NEED_LDST_LABELS
> > diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
> > index d8797ed398..e9c128d9e7 100644
> > --- a/tcg/i386/tcg-target.c.inc
> > +++ b/tcg/i386/tcg-target.c.inc
> > @@ -165,9 +165,9 @@ static bool have_lzcnt;
> > # define have_lzcnt 0
> > #endif
> >
> > -static tcg_insn_unit *tb_ret_addr;
> > +static const tcg_insn_unit *tb_ret_addr;
> >
> > -static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
> > +static bool patch_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type,
> >                         intptr_t value, intptr_t addend)
> > {
> >     value += addend;
> > @@ -179,14 +179,14 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int 
> > type,
> >         }
> >         /* FALLTHRU */
> >     case R_386_32:
> > -        tcg_patch32(code_ptr, value);
> > +        tcg_patch32(s, code_ptr, value);
> >         break;
> >     case R_386_PC8:
> >         value -= (uintptr_t)code_ptr;
> >         if (value != (int8_t)value) {
> >             return false;
> >         }
> > -        tcg_patch8(code_ptr, value);
> > +        tcg_patch8(s, code_ptr, value);
> >         break;
> >     default:
> >         tcg_abort();
> > @@ -1591,7 +1591,7 @@ static void tcg_out_clz(TCGContext *s, int rexw, 
> > TCGReg dest, TCGReg arg1,
> >     }
> > }
> >
> > -static void tcg_out_branch(TCGContext *s, int call, tcg_insn_unit *dest)
> > +static void tcg_out_branch(TCGContext *s, int call, const tcg_insn_unit 
> > *dest)
> > {
> >     intptr_t disp = tcg_pcrel_diff(s, dest) - 5;
> >
> > @@ -1610,12 +1610,12 @@ static void tcg_out_branch(TCGContext *s, int call, 
> > tcg_insn_unit *dest)
> >     }
> > }
> >
> > -static inline void tcg_out_call(TCGContext *s, tcg_insn_unit *dest)
> > +static inline void tcg_out_call(TCGContext *s, const tcg_insn_unit *dest)
> > {
> >     tcg_out_branch(s, 1, dest);
> > }
> >
> > -static void tcg_out_jmp(TCGContext *s, tcg_insn_unit *dest)
> > +static void tcg_out_jmp(TCGContext *s, const tcg_insn_unit *dest)
> > {
> >     tcg_out_branch(s, 0, dest);
> > }
> > @@ -1774,7 +1774,7 @@ static void add_qemu_ldst_label(TCGContext *s, bool 
> > is_ld, bool is_64,
> >                                 TCGMemOpIdx oi,
> >                                 TCGReg datalo, TCGReg datahi,
> >                                 TCGReg addrlo, TCGReg addrhi,
> > -                                tcg_insn_unit *raddr,
> > +                                const tcg_insn_unit *raddr,
> >                                 tcg_insn_unit **label_ptr)
> > {
> >     TCGLabelQemuLdst *label = new_ldst_label(s);
> > @@ -1805,9 +1805,9 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *l)
> >     int rexw = (l->type == TCG_TYPE_I64 ? P_REXW : 0);
> >
> >     /* resolve label address */
> > -    tcg_patch32(label_ptr[0], s->code_ptr - label_ptr[0] - 4);
> > +    tcg_patch32(s, label_ptr[0], s->code_ptr - label_ptr[0] - 4);
> >     if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
> > -        tcg_patch32(label_ptr[1], s->code_ptr - label_ptr[1] - 4);
> > +        tcg_patch32(s, label_ptr[1], s->code_ptr - label_ptr[1] - 4);
> >     }
> >
> >     if (TCG_TARGET_REG_BITS == 32) {
> > @@ -1890,9 +1890,9 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *l)
> >     TCGReg retaddr;
> >
> >     /* resolve label address */
> > -    tcg_patch32(label_ptr[0], s->code_ptr - label_ptr[0] - 4);
> > +    tcg_patch32(s, label_ptr[0], s->code_ptr - label_ptr[0] - 4);
> >     if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
> > -        tcg_patch32(label_ptr[1], s->code_ptr - label_ptr[1] - 4);
> > +        tcg_patch32(s, label_ptr[1], s->code_ptr - label_ptr[1] - 4);
> >     }
> >
> >     if (TCG_TARGET_REG_BITS == 32) {
> > @@ -3842,9 +3842,9 @@ static void tcg_target_qemu_prologue(TCGContext *s)
> >     tcg_out_opc(s, OPC_RET, 0, 0, 0);
> > }
> >
> > -static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
> > +static void tcg_out_nop_fill(TCGContext *s, tcg_insn_unit *p, int count)
> > {
> > -    memset(p, 0x90, count);
> > +    memset(TCG_CODE_PTR_RW(s, p), 0x90, count);
> > }
> >
> > static void tcg_target_init(TCGContext *s)
> > diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
> > index abd4ac7fc0..cdc440ce36 100644
> > --- a/tcg/i386/tcg-target.h
> > +++ b/tcg/i386/tcg-target.h
> > @@ -206,16 +206,36 @@ extern bool have_avx2;
> > #define TCG_TARGET_extract_i64_valid(ofs, len) \
> >     (((ofs) == 8 && (len) == 8) || ((ofs) + (len)) == 32)
> >
> > +#ifdef __APPLE__
> > +void sys_dcache_flush(void *start, size_t len);
> > +#endif
> > +
> > static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
> > {
> > }
> >
> > +#if defined(CONFIG_IOS_JIT)
> > +static inline void flush_dcache_range(uintptr_t start, uintptr_t stop)
> > +{
> > +#if defined(__APPLE__)
> > +    sys_dcache_flush((char *)start, stop - start);
> > +#else
> > +#error "Missing function to flush data cache"
> > +#endif
> > +}
> > +#endif
> > +
> > static inline void tb_target_set_jmp_target(uintptr_t tc_ptr,
> > -                                            uintptr_t jmp_addr, uintptr_t 
> > addr)
> > +                                            uintptr_t jmp_addr, uintptr_t 
> > addr,
> > +                                            uintptr_t wr_addr)
> > {
> >     /* patch the branch destination */
> > -    qatomic_set((int32_t *)jmp_addr, addr - (jmp_addr + 4));
> > +    qatomic_set((int32_t *)wr_addr, addr - (jmp_addr + 4));
> >     /* no need to flush icache explicitly */
> > +#if defined(CONFIG_IOS_JIT)
> > +    /* we do need to flush mirror dcache */
> > +    flush_dcache_range(wr_addr, wr_addr + 4);
> > +#endif
> > }
> >
> > /* This defines the natural memory order supported by this
> > diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
> > index 41be574e89..e798527437 100644
> > --- a/tcg/mips/tcg-target.c.inc
> > +++ b/tcg/mips/tcg-target.c.inc
> > @@ -139,12 +139,13 @@ static const TCGReg tcg_target_call_oarg_regs[2] = {
> >     TCG_REG_V1
> > };
> >
> > -static tcg_insn_unit *tb_ret_addr;
> > -static tcg_insn_unit *bswap32_addr;
> > -static tcg_insn_unit *bswap32u_addr;
> > -static tcg_insn_unit *bswap64_addr;
> > +static const tcg_insn_unit *tb_ret_addr;
> > +static const tcg_insn_unit *bswap32_addr;
> > +static const tcg_insn_unit *bswap32u_addr;
> > +static const tcg_insn_unit *bswap64_addr;
> >
> > -static inline uint32_t reloc_pc16_val(tcg_insn_unit *pc, tcg_insn_unit 
> > *target)
> > +static inline uint32_t reloc_pc16_val(const tcg_insn_unit *pc,
> > +                                      const tcg_insn_unit *target)
> > {
> >     /* Let the compiler perform the right-shift as part of the arithmetic.  
> > */
> >     ptrdiff_t disp = target - (pc + 1);
> > @@ -152,28 +153,35 @@ static inline uint32_t reloc_pc16_val(tcg_insn_unit 
> > *pc, tcg_insn_unit *target)
> >     return disp & 0xffff;
> > }
> >
> > -static inline void reloc_pc16(tcg_insn_unit *pc, tcg_insn_unit *target)
> > +static inline void reloc_pc16(TCGContext *s,
> > +                              tcg_insn_unit *pc,
> > +                              const tcg_insn_unit *target)
> > {
> > -    *pc = deposit32(*pc, 0, 16, reloc_pc16_val(pc, target));
> > +    *TCG_CODE_PTR_RW(s, pc) =
> > +        deposit32(*TCG_CODE_PTR_RW(s, pc), 0, 16, reloc_pc16_val(pc, 
> > target));
> > }
> >
> > -static inline uint32_t reloc_26_val(tcg_insn_unit *pc, tcg_insn_unit 
> > *target)
> > +static inline uint32_t reloc_26_val(const tcg_insn_unit *pc,
> > +                                    const tcg_insn_unit *target)
> > {
> >     tcg_debug_assert((((uintptr_t)pc ^ (uintptr_t)target) & 0xf0000000) == 
> > 0);
> >     return ((uintptr_t)target >> 2) & 0x3ffffff;
> > }
> >
> > -static inline void reloc_26(tcg_insn_unit *pc, tcg_insn_unit *target)
> > +static inline void reloc_26(TCGContext *s,
> > +                            tcg_insn_unit *pc,
> > +                            const tcg_insn_unit *target)
> > {
> > -    *pc = deposit32(*pc, 0, 26, reloc_26_val(pc, target));
> > +    *TCG_CODE_PTR_RW(s, pc) =
> > +        deposit32(*TCG_CODE_PTR_RW(s, pc), 0, 26, reloc_26_val(pc, 
> > target));
> > }
> >
> > -static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
> > +static bool patch_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type,
> >                         intptr_t value, intptr_t addend)
> > {
> >     tcg_debug_assert(type == R_MIPS_PC16);
> >     tcg_debug_assert(addend == 0);
> > -    reloc_pc16(code_ptr, (tcg_insn_unit *)value);
> > +    reloc_pc16(s, code_ptr, (tcg_insn_unit *)value);
> >     return true;
> > }
> >
> > @@ -516,7 +524,7 @@ static void tcg_out_opc_sa64(TCGContext *s, MIPSInsn 
> > opc1, MIPSInsn opc2,
> >  * Type jump.
> >  * Returns true if the branch was in range and the insn was emitted.
> >  */
> > -static bool tcg_out_opc_jmp(TCGContext *s, MIPSInsn opc, void *target)
> > +static bool tcg_out_opc_jmp(TCGContext *s, MIPSInsn opc, const void 
> > *target)
> > {
> >     uintptr_t dest = (uintptr_t)target;
> >     uintptr_t from = (uintptr_t)s->code_ptr + 4;
> > @@ -631,7 +639,7 @@ static inline void tcg_out_bswap16s(TCGContext *s, 
> > TCGReg ret, TCGReg arg)
> >     }
> > }
> >
> > -static void tcg_out_bswap_subr(TCGContext *s, tcg_insn_unit *sub)
> > +static void tcg_out_bswap_subr(TCGContext *s, const tcg_insn_unit *sub)
> > {
> >     bool ok = tcg_out_opc_jmp(s, OPC_JAL, sub);
> >     tcg_debug_assert(ok);
> > @@ -925,7 +933,7 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, 
> > TCGReg arg1,
> >
> >     tcg_out_opc_br(s, b_opc, arg1, arg2);
> >     if (l->has_value) {
> > -        reloc_pc16(s->code_ptr - 1, l->u.value_ptr);
> > +        reloc_pc16(s, s->code_ptr - 1, l->u.value_ptr);
> >     } else {
> >         tcg_out_reloc(s, s->code_ptr - 1, R_MIPS_PC16, l, 0);
> >     }
> > @@ -1079,7 +1087,7 @@ static void tcg_out_movcond(TCGContext *s, TCGCond 
> > cond, TCGReg ret,
> >     }
> > }
> >
> > -static void tcg_out_call_int(TCGContext *s, tcg_insn_unit *arg, bool tail)
> > +static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool 
> > tail)
> > {
> >     /* Note that the ABI requires the called function's address to be
> >        loaded into T9, even if a direct branch is in range.  */
> > @@ -1097,7 +1105,7 @@ static void tcg_out_call_int(TCGContext *s, 
> > tcg_insn_unit *arg, bool tail)
> >     }
> > }
> >
> > -static void tcg_out_call(TCGContext *s, tcg_insn_unit *arg)
> > +static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg)
> > {
> >     tcg_out_call_int(s, arg, false);
> >     tcg_out_nop(s);
> > @@ -1289,7 +1297,8 @@ static void add_qemu_ldst_label(TCGContext *s, int 
> > is_ld, TCGMemOpIdx oi,
> >                                 TCGType ext,
> >                                 TCGReg datalo, TCGReg datahi,
> >                                 TCGReg addrlo, TCGReg addrhi,
> > -                                void *raddr, tcg_insn_unit *label_ptr[2])
> > +                                const tcg_insn_unit *raddr,
> > +                                tcg_insn_unit *label_ptr[2])
> > {
> >     TCGLabelQemuLdst *label = new_ldst_label(s);
> >
> > @@ -1315,9 +1324,9 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *l)
> >     int i;
> >
> >     /* resolve label address */
> > -    reloc_pc16(l->label_ptr[0], s->code_ptr);
> > +    reloc_pc16(s, l->label_ptr[0], s->code_ptr);
> >     if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
> > -        reloc_pc16(l->label_ptr[1], s->code_ptr);
> > +        reloc_pc16(s, l->label_ptr[1], s->code_ptr);
> >     }
> >
> >     i = 1;
> > @@ -1345,7 +1354,7 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *l)
> >     }
> >
> >     tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
> > -    reloc_pc16(s->code_ptr - 1, l->raddr);
> > +    reloc_pc16(s, s->code_ptr - 1, l->raddr);
> >
> >     /* delay slot */
> >     if (TCG_TARGET_REG_BITS == 64 && l->type == TCG_TYPE_I32) {
> > @@ -1365,9 +1374,9 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *l)
> >     int i;
> >
> >     /* resolve label address */
> > -    reloc_pc16(l->label_ptr[0], s->code_ptr);
> > +    reloc_pc16(s, l->label_ptr[0], s->code_ptr);
> >     if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
> > -        reloc_pc16(l->label_ptr[1], s->code_ptr);
> > +        reloc_pc16(s, l->label_ptr[1], s->code_ptr);
> >     }
> >
> >     i = 1;
> > @@ -2430,7 +2439,7 @@ static void tcg_target_detect_isa(void)
> >     sigaction(SIGILL, &sa_old, NULL);
> > }
> >
> > -static tcg_insn_unit *align_code_ptr(TCGContext *s)
> > +static const tcg_insn_unit *align_code_ptr(TCGContext *s)
> > {
> >     uintptr_t p = (uintptr_t)s->code_ptr;
> >     if (p & 15) {
> > @@ -2657,9 +2666,12 @@ static void tcg_target_init(TCGContext *s)
> > }
> >
> > void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr,
> > -                              uintptr_t addr)
> > +                              uintptr_t addr, uintptr_t wr_addr)
> > {
> > -    qatomic_set((uint32_t *)jmp_addr, deposit32(OPC_J, 0, 26, addr >> 2));
> > +    qatomic_set((uint32_t *)wr_addr, deposit32(OPC_J, 0, 26, addr >> 2));
> > +#if defined(CONFIG_IOS_JIT)
> > +    flush_dcache_range(wr_addr, wr_addr + 4);
> > +#endif
> >     flush_icache_range(jmp_addr, jmp_addr + 4);
> > }
> >
> > diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
> > index c6b091d849..80dcba5358 100644
> > --- a/tcg/mips/tcg-target.h
> > +++ b/tcg/mips/tcg-target.h
> > @@ -212,7 +212,13 @@ static inline void flush_icache_range(uintptr_t start, 
> > uintptr_t stop)
> >     cacheflush ((void *)start, stop-start, ICACHE);
> > }
> >
> > -void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
> > +void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
> > +#if defined(CONFIG_IOS_JIT)
> > +static inline void flush_dcache_range(uintptr_t start, uintptr_t stop)
> > +{
> > +#error "Unimplemented dcache flush function"
> > +}
> > +#endif
> >
> > #ifdef CONFIG_SOFTMMU
> > #define TCG_TARGET_NEED_LDST_LABELS
> > diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
> > index 18ee989f95..f5a44e9852 100644
> > --- a/tcg/ppc/tcg-target.c.inc
> > +++ b/tcg/ppc/tcg-target.c.inc
> > @@ -62,7 +62,7 @@
> > #define TCG_CT_CONST_MONE 0x2000
> > #define TCG_CT_CONST_WSZ  0x4000
> >
> > -static tcg_insn_unit *tb_ret_addr;
> > +static const tcg_insn_unit *tb_ret_addr;
> >
> > TCGPowerISA have_isa;
> > static bool have_isel;
> > @@ -184,35 +184,43 @@ static inline bool in_range_b(tcg_target_long target)
> >     return target == sextract64(target, 0, 26);
> > }
> >
> > -static uint32_t reloc_pc24_val(tcg_insn_unit *pc, tcg_insn_unit *target)
> > +static uint32_t reloc_pc24_val(const tcg_insn_unit *pc,
> > +                               const tcg_insn_unit *target)
> > {
> >     ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
> >     tcg_debug_assert(in_range_b(disp));
> >     return disp & 0x3fffffc;
> > }
> >
> > -static bool reloc_pc24(tcg_insn_unit *pc, tcg_insn_unit *target)
> > +static bool reloc_pc24(TCGContext *s,
> > +                       tcg_insn_unit *pc,
> > +                       const tcg_insn_unit *target)
> > {
> >     ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
> >     if (in_range_b(disp)) {
> > -        *pc = (*pc & ~0x3fffffc) | (disp & 0x3fffffc);
> > +        *TCG_CODE_PTR_RW(s, pc) =
> > +            (*TCG_CODE_PTR_RW(s, pc) & ~0x3fffffc) | (disp & 0x3fffffc);
> >         return true;
> >     }
> >     return false;
> > }
> >
> > -static uint16_t reloc_pc14_val(tcg_insn_unit *pc, tcg_insn_unit *target)
> > +static uint16_t reloc_pc14_val(const tcg_insn_unit *pc,
> > +                               const tcg_insn_unit *target)
> > {
> >     ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
> >     tcg_debug_assert(disp == (int16_t) disp);
> >     return disp & 0xfffc;
> > }
> >
> > -static bool reloc_pc14(tcg_insn_unit *pc, tcg_insn_unit *target)
> > +static bool reloc_pc14(TCGContext *s,
> > +                       tcg_insn_unit *pc,
> > +                       const tcg_insn_unit *target)
> > {
> >     ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
> >     if (disp == (int16_t) disp) {
> > -        *pc = (*pc & ~0xfffc) | (disp & 0xfffc);
> > +        *TCG_CODE_PTR_RW(s, pc) =
> > +            (*TCG_CODE_PTR_RW(s, pc) & ~0xfffc) | (disp & 0xfffc);
> >         return true;
> >     }
> >     return false;
> > @@ -670,7 +678,7 @@ static const uint32_t tcg_to_isel[] = {
> >     [TCG_COND_GTU] = ISEL | BC_(7, CR_GT),
> > };
> >
> > -static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
> > +static bool patch_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type,
> >                         intptr_t value, intptr_t addend)
> > {
> >     tcg_insn_unit *target;
> > @@ -682,9 +690,9 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int 
> > type,
> >
> >     switch (type) {
> >     case R_PPC_REL14:
> > -        return reloc_pc14(code_ptr, target);
> > +        return reloc_pc14(s, code_ptr, target);
> >     case R_PPC_REL24:
> > -        return reloc_pc24(code_ptr, target);
> > +        return reloc_pc24(s, code_ptr, target);
> >     case R_PPC_ADDR16:
> >         /*
> >          * We are (slightly) abusing this relocation type.  In particular,
> > @@ -1106,7 +1114,7 @@ static void tcg_out_xori32(TCGContext *s, TCGReg dst, 
> > TCGReg src, uint32_t c)
> >     tcg_out_zori32(s, dst, src, c, XORI, XORIS);
> > }
> >
> > -static void tcg_out_b(TCGContext *s, int mask, tcg_insn_unit *target)
> > +static void tcg_out_b(TCGContext *s, int mask, const tcg_insn_unit *target)
> > {
> >     ptrdiff_t disp = tcg_pcrel_diff(s, target);
> >     if (in_range_b(disp)) {
> > @@ -1723,7 +1731,7 @@ static void tcg_out_mb(TCGContext *s, TCGArg a0)
> > }
> >
> > void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr,
> > -                              uintptr_t addr)
> > +                              uintptr_t addr, uintptr_t wr_addr)
> > {
> >     if (TCG_TARGET_REG_BITS == 64) {
> >         tcg_insn_unit i1, i2;
> > @@ -1752,17 +1760,23 @@ void tb_target_set_jmp_target(uintptr_t tc_ptr, 
> > uintptr_t jmp_addr,
> >
> >         /* As per the enclosing if, this is ppc64.  Avoid the _Static_assert
> >            within qatomic_set that would fail to build a ppc32 host.  */
> > -        qatomic_set__nocheck((uint64_t *)jmp_addr, pair);
> > +        qatomic_set__nocheck((uint64_t *)wr_addr, pair);
> > +#if defined(CONFIG_IOS_JIT)
> > +        flush_dcache_range(wr_addr, wr_addr + 8);
> > +#endif
> >         flush_icache_range(jmp_addr, jmp_addr + 8);
> >     } else {
> >         intptr_t diff = addr - jmp_addr;
> >         tcg_debug_assert(in_range_b(diff));
> > -        qatomic_set((uint32_t *)jmp_addr, B | (diff & 0x3fffffc));
> > +        qatomic_set((uint32_t *)wr_addr, B | (diff & 0x3fffffc));
> > +#if defined(CONFIG_IOS_JIT)
> > +        flush_dcache_range(wr_addr, wr_addr + 8);
> > +#endif
> >         flush_icache_range(jmp_addr, jmp_addr + 4);
> >     }
> > }
> >
> > -static void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
> > +static void tcg_out_call(TCGContext *s, const tcg_insn_unit *target)
> > {
> > #ifdef _CALL_AIX
> >     /* Look through the descriptor.  If the branch is in range, and we
> > @@ -1987,7 +2001,8 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, MemOp 
> > opc,
> > static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
> >                                 TCGReg datalo_reg, TCGReg datahi_reg,
> >                                 TCGReg addrlo_reg, TCGReg addrhi_reg,
> > -                                tcg_insn_unit *raddr, tcg_insn_unit *lptr)
> > +                                const tcg_insn_unit *raddr,
> > +                                tcg_insn_unit *lptr)
> > {
> >     TCGLabelQemuLdst *label = new_ldst_label(s);
> >
> > @@ -2007,7 +2022,7 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *lb)
> >     MemOp opc = get_memop(oi);
> >     TCGReg hi, lo, arg = TCG_REG_R3;
> >
> > -    if (!reloc_pc14(lb->label_ptr[0], s->code_ptr)) {
> > +    if (!reloc_pc14(s, lb->label_ptr[0], s->code_ptr)) {
> >         return false;
> >     }
> >
> > @@ -2055,7 +2070,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *lb)
> >     MemOp s_bits = opc & MO_SIZE;
> >     TCGReg hi, lo, arg = TCG_REG_R3;
> >
> > -    if (!reloc_pc14(lb->label_ptr[0], s->code_ptr)) {
> > +    if (!reloc_pc14(s, lb->label_ptr[0], s->code_ptr)) {
> >         return false;
> >     }
> >
> > @@ -2252,11 +2267,11 @@ static void tcg_out_qemu_st(TCGContext *s, const 
> > TCGArg *args, bool is_64)
> > #endif
> > }
> >
> > -static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
> > +static void tcg_out_nop_fill(TCGContext *s, tcg_insn_unit *p, int count)
> > {
> >     int i;
> >     for (i = 0; i < count; ++i) {
> > -        p[i] = NOP;
> > +        (TCG_CODE_PTR_RW(s, p))[i] = NOP;
> >     }
> > }
> >
> > diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
> > index be10363956..23d7a337c9 100644
> > --- a/tcg/ppc/tcg-target.h
> > +++ b/tcg/ppc/tcg-target.h
> > @@ -176,7 +176,13 @@ extern bool have_vsx;
> > #define TCG_TARGET_HAS_cmpsel_vec       0
> >
> > void flush_icache_range(uintptr_t start, uintptr_t stop);
> > -void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
> > +void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
> > +#if defined(CONFIG_IOS_JIT)
> > +static inline void flush_dcache_range(uintptr_t start, uintptr_t stop)
> > +{
> > +#error "Unimplemented dcache flush function"
> > +}
> > +#endif
> >
> > #define TCG_TARGET_DEFAULT_MO (0)
> > #define TCG_TARGET_HAS_MEMORY_BSWAP     1
> > diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
> > index d536f3ccc1..2d96c83c4b 100644
> > --- a/tcg/riscv/tcg-target.c.inc
> > +++ b/tcg/riscv/tcg-target.c.inc
> > @@ -413,11 +413,11 @@ static void tcg_out_opc_jump(TCGContext *s, RISCVInsn 
> > opc,
> >     tcg_out32(s, encode_uj(opc, rd, imm));
> > }
> >
> > -static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
> > +static void tcg_out_nop_fill(TCGContext *s, tcg_insn_unit *p, int count)
> > {
> >     int i;
> >     for (i = 0; i < count; ++i) {
> > -        p[i] = encode_i(OPC_ADDI, TCG_REG_ZERO, TCG_REG_ZERO, 0);
> > +        (TCG_CODE_PTR_RW(s, p))[i] = encode_i(OPC_ADDI, TCG_REG_ZERO, 
> > TCG_REG_ZERO, 0);
> >     }
> > }
> >
> > @@ -425,46 +425,52 @@ static void tcg_out_nop_fill(tcg_insn_unit *p, int 
> > count)
> >  * Relocations
> >  */
> >
> > -static bool reloc_sbimm12(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
> > +static bool reloc_sbimm12(TCGContext *s,
> > +                          tcg_insn_unit *code_ptr,
> > +                          const tcg_insn_unit *target)
> > {
> >     intptr_t offset = (intptr_t)target - (intptr_t)code_ptr;
> >
> >     if (offset == sextreg(offset, 1, 12) << 1) {
> > -        code_ptr[0] |= encode_sbimm12(offset);
> > +        (TCG_CODE_PTR_RW(s, code_ptr))[0] |= encode_sbimm12(offset);
> >         return true;
> >     }
> >
> >     return false;
> > }
> >
> > -static bool reloc_jimm20(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
> > +static bool reloc_jimm20(TCGContext *s,
> > +                         tcg_insn_unit *code_ptr,
> > +                         const tcg_insn_unit *target)
> > {
> >     intptr_t offset = (intptr_t)target - (intptr_t)code_ptr;
> >
> >     if (offset == sextreg(offset, 1, 20) << 1) {
> > -        code_ptr[0] |= encode_ujimm20(offset);
> > +        (TCG_CODE_PTR_RW(s, code_ptr))[0] |= encode_ujimm20(offset);
> >         return true;
> >     }
> >
> >     return false;
> > }
> >
> > -static bool reloc_call(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
> > +static bool reloc_call(TCGContext *s,
> > +                       tcg_insn_unit *code_ptr,
> > +                       const tcg_insn_unit *target)
> > {
> >     intptr_t offset = (intptr_t)target - (intptr_t)code_ptr;
> >     int32_t lo = sextreg(offset, 0, 12);
> >     int32_t hi = offset - lo;
> >
> >     if (offset == hi + lo) {
> > -        code_ptr[0] |= encode_uimm20(hi);
> > -        code_ptr[1] |= encode_imm12(lo);
> > +        (TCG_CODE_PTR_RW(s, code_ptr))[0] |= encode_uimm20(hi);
> > +        (TCG_CODE_PTR_RW(s, code_ptr))[1] |= encode_imm12(lo);
> >         return true;
> >     }
> >
> >     return false;
> > }
> >
> > -static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
> > +static bool patch_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type,
> >                         intptr_t value, intptr_t addend)
> > {
> >     uint32_t insn = *code_ptr;
> > @@ -478,7 +484,7 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int 
> > type,
> >         diff = value - (uintptr_t)code_ptr;
> >         short_jmp = diff == sextreg(diff, 0, 12);
> >         if (short_jmp) {
> > -            return reloc_sbimm12(code_ptr, (tcg_insn_unit *)value);
> > +            return reloc_sbimm12(s, code_ptr, (tcg_insn_unit *)value);
> >         } else {
> >             /* Invert the condition */
> >             insn = insn ^ (1 << 12);
> > @@ -499,9 +505,9 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int 
> > type,
> >         }
> >         break;
> >     case R_RISCV_JAL:
> > -        return reloc_jimm20(code_ptr, (tcg_insn_unit *)value);
> > +        return reloc_jimm20(s, code_ptr, (tcg_insn_unit *)value);
> >     case R_RISCV_CALL:
> > -        return reloc_call(code_ptr, (tcg_insn_unit *)value);
> > +        return reloc_call(s, code_ptr, (tcg_insn_unit *)value);
> >     default:
> >         tcg_abort();
> >     }
> > @@ -557,7 +563,7 @@ static void tcg_out_movi(TCGContext *s, TCGType type, 
> > TCGReg rd,
> >     if (tmp == (int32_t)tmp) {
> >         tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
> >         tcg_out_opc_imm(s, OPC_ADDI, rd, rd, 0);
> > -        ret = reloc_call(s->code_ptr - 2, (tcg_insn_unit *)val);
> > +        ret = reloc_call(s, s->code_ptr - 2, (tcg_insn_unit *)val);
> >         tcg_debug_assert(ret == true);
> >         return;
> >     }
> > @@ -854,14 +860,14 @@ static void tcg_out_setcond2(TCGContext *s, TCGCond 
> > cond, TCGReg ret,
> >     g_assert_not_reached();
> > }
> >
> > -static inline void tcg_out_goto(TCGContext *s, tcg_insn_unit *target)
> > +static inline void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
> > {
> >     ptrdiff_t offset = tcg_pcrel_diff(s, target);
> >     tcg_debug_assert(offset == sextreg(offset, 1, 20) << 1);
> >     tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, offset);
> > }
> >
> > -static void tcg_out_call_int(TCGContext *s, tcg_insn_unit *arg, bool tail)
> > +static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool 
> > tail)
> > {
> >     TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
> >     ptrdiff_t offset = tcg_pcrel_diff(s, arg);
> > @@ -875,7 +881,7 @@ static void tcg_out_call_int(TCGContext *s, 
> > tcg_insn_unit *arg, bool tail)
> >         /* long jump: -2147483646 to 2147483648 */
> >         tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP0, 0);
> >         tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, 0);
> > -        ret = reloc_call(s->code_ptr - 2, arg);\
> > +        ret = reloc_call(s, s->code_ptr - 2, arg);\
> >         tcg_debug_assert(ret == true);
> >     } else if (TCG_TARGET_REG_BITS == 64) {
> >         /* far jump: 64-bit */
> > @@ -888,7 +894,7 @@ static void tcg_out_call_int(TCGContext *s, 
> > tcg_insn_unit *arg, bool tail)
> >     }
> > }
> >
> > -static void tcg_out_call(TCGContext *s, tcg_insn_unit *arg)
> > +static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg)
> > {
> >     tcg_out_call_int(s, arg, false);
> > }
> > @@ -1022,7 +1028,8 @@ static void add_qemu_ldst_label(TCGContext *s, int 
> > is_ld, TCGMemOpIdx oi,
> >                                 TCGType ext,
> >                                 TCGReg datalo, TCGReg datahi,
> >                                 TCGReg addrlo, TCGReg addrhi,
> > -                                void *raddr, tcg_insn_unit **label_ptr)
> > +                                const tcg_insn_unit *raddr,
> > +                                tcg_insn_unit **label_ptr)
> > {
> >     TCGLabelQemuLdst *label = new_ldst_label(s);
> >
> > @@ -1052,7 +1059,7 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *l)
> >     }
> >
> >     /* resolve label address */
> > -    if (!patch_reloc(l->label_ptr[0], R_RISCV_BRANCH,
> > +    if (!patch_reloc(s, l->label_ptr[0], R_RISCV_BRANCH,
> >                      (intptr_t) s->code_ptr, 0)) {
> >         return false;
> >     }
> > @@ -1087,7 +1094,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *l)
> >     }
> >
> >     /* resolve label address */
> > -    if (!patch_reloc(l->label_ptr[0], R_RISCV_BRANCH,
> > +    if (!patch_reloc(s, l->label_ptr[0], R_RISCV_BRANCH,
> >                      (intptr_t) s->code_ptr, 0)) {
> >         return false;
> >     }
> > @@ -1274,7 +1281,7 @@ static void tcg_out_qemu_st(TCGContext *s, const 
> > TCGArg *args, bool is_64)
> > #endif
> > }
> >
> > -static tcg_insn_unit *tb_ret_addr;
> > +static const tcg_insn_unit *tb_ret_addr;
> >
> > static void tcg_out_op(TCGContext *s, TCGOpcode opc,
> >                        const TCGArg *args, const int *const_args)
> > diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> > index 032439d806..d42b361991 100644
> > --- a/tcg/riscv/tcg-target.h
> > +++ b/tcg/riscv/tcg-target.h
> > @@ -164,8 +164,15 @@ static inline void flush_icache_range(uintptr_t start, 
> > uintptr_t stop)
> >     __builtin___clear_cache((char *)start, (char *)stop);
> > }
> >
> > +#if defined(CONFIG_IOS_JIT)
> > +static inline void flush_dcache_range(uintptr_t start, uintptr_t stop)
> > +{
> > +#error "Unimplemented dcache flush function"
> > +}
> > +#endif
> > +
> > /* not defined -- call should be eliminated at compile time */
> > -void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
> > +void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
> >
> > #define TCG_TARGET_DEFAULT_MO (0)
> >
> > diff --git a/tcg/s390/tcg-target.c.inc b/tcg/s390/tcg-target.c.inc
> > index c5e096449b..49a96ca15f 100644
> > --- a/tcg/s390/tcg-target.c.inc
> > +++ b/tcg/s390/tcg-target.c.inc
> > @@ -363,10 +363,10 @@ static void * const qemu_st_helpers[16] = {
> > };
> > #endif
> >
> > -static tcg_insn_unit *tb_ret_addr;
> > +static const tcg_insn_unit *tb_ret_addr;
> > uint64_t s390_facilities;
> >
> > -static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
> > +static bool patch_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type,
> >                         intptr_t value, intptr_t addend)
> > {
> >     intptr_t pcrel2;
> > @@ -378,13 +378,13 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int 
> > type,
> >     switch (type) {
> >     case R_390_PC16DBL:
> >         if (pcrel2 == (int16_t)pcrel2) {
> > -            tcg_patch16(code_ptr, pcrel2);
> > +            tcg_patch16(s, code_ptr, pcrel2);
> >             return true;
> >         }
> >         break;
> >     case R_390_PC32DBL:
> >         if (pcrel2 == (int32_t)pcrel2) {
> > -            tcg_patch32(code_ptr, pcrel2);
> > +            tcg_patch32(s, code_ptr, pcrel2);
> >             return true;
> >         }
> >         break;
> > @@ -392,7 +392,7 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int 
> > type,
> >         if (value == sextract64(value, 0, 20)) {
> >             old = *(uint32_t *)code_ptr & 0xf00000ff;
> >             old |= ((value & 0xfff) << 16) | ((value & 0xff000) >> 4);
> > -            tcg_patch32(code_ptr, old);
> > +            tcg_patch32(s, code_ptr, old);
> >             return true;
> >         }
> >         break;
> > @@ -1302,7 +1302,7 @@ static void tgen_extract(TCGContext *s, TCGReg dest, 
> > TCGReg src,
> >     tcg_out_risbg(s, dest, src, 64 - len, 63, 64 - ofs, 1);
> > }
> >
> > -static void tgen_gotoi(TCGContext *s, int cc, tcg_insn_unit *dest)
> > +static void tgen_gotoi(TCGContext *s, int cc, const tcg_insn_unit *dest)
> > {
> >     ptrdiff_t off = dest - s->code_ptr;
> >     if (off == (int16_t)off) {
> > @@ -1415,7 +1415,7 @@ static void tgen_brcond(TCGContext *s, TCGType type, 
> > TCGCond c,
> >     tgen_branch(s, cc, l);
> > }
> >
> > -static void tcg_out_call(TCGContext *s, tcg_insn_unit *dest)
> > +static void tcg_out_call(TCGContext *s, const tcg_insn_unit *dest)
> > {
> >     ptrdiff_t off = dest - s->code_ptr;
> >     if (off == (int32_t)off) {
> > @@ -1593,7 +1593,8 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg 
> > addr_reg, MemOp opc,
> >
> > static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
> >                                 TCGReg data, TCGReg addr,
> > -                                tcg_insn_unit *raddr, tcg_insn_unit 
> > *label_ptr)
> > +                                const tcg_insn_unit *raddr,
> > +                                tcg_insn_unit *label_ptr)
> > {
> >     TCGLabelQemuLdst *label = new_ldst_label(s);
> >
> > @@ -1612,7 +1613,7 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *lb)
> >     TCGMemOpIdx oi = lb->oi;
> >     MemOp opc = get_memop(oi);
> >
> > -    if (!patch_reloc(lb->label_ptr[0], R_390_PC16DBL,
> > +    if (!patch_reloc(s, lb->label_ptr[0], R_390_PC16DBL,
> >                      (intptr_t)s->code_ptr, 2)) {
> >         return false;
> >     }
> > @@ -1637,7 +1638,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
> > TCGLabelQemuLdst *lb)
> >     TCGMemOpIdx oi = lb->oi;
> >     MemOp opc = get_memop(oi);
> >
> > -    if (!patch_reloc(lb->label_ptr[0], R_390_PC16DBL,
> > +    if (!patch_reloc(s, lb->label_ptr[0], R_390_PC16DBL,
> >                      (intptr_t)s->code_ptr, 2)) {
> >         return false;
> >     }
> > @@ -2575,9 +2576,9 @@ static void tcg_target_qemu_prologue(TCGContext *s)
> >     tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, TCG_REG_R14);
> > }
> >
> > -static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
> > +static void tcg_out_nop_fill(TCGContext *s, tcg_insn_unit *p, int count)
> > {
> > -    memset(p, 0x07, count * sizeof(tcg_insn_unit));
> > +    memset(TCG_CODE_PTR_RW(s, p), 0x07, count * sizeof(tcg_insn_unit));
> > }
> >
> > typedef struct {
> > diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h
> > index 63c8797bd3..d67632512d 100644
> > --- a/tcg/s390/tcg-target.h
> > +++ b/tcg/s390/tcg-target.h
> > @@ -149,13 +149,24 @@ static inline void flush_icache_range(uintptr_t 
> > start, uintptr_t stop)
> > {
> > }
> >
> > +#if defined(CONFIG_IOS_JIT)
> > +static inline void flush_dcache_range(uintptr_t start, uintptr_t stop)
> > +{
> > +#error "Unimplemented dcache flush function"
> > +}
> > +#endif
> > +
> > static inline void tb_target_set_jmp_target(uintptr_t tc_ptr,
> > -                                            uintptr_t jmp_addr, uintptr_t 
> > addr)
> > +                                            uintptr_t jmp_addr, uintptr_t 
> > addr,
> > +                                            uintptr_t wr_addr)
> > {
> >     /* patch the branch destination */
> >     intptr_t disp = addr - (jmp_addr - 2);
> >     qatomic_set((int32_t *)jmp_addr, disp / 2);
> >     /* no need to flush icache explicitly */
> > +#if defined(CONFIG_IOS_JIT)
> > +    flush_dcache_range(wr_addr, wr_addr + 4);
> > +#endif
> > }
> >
> > #ifdef CONFIG_SOFTMMU
> > diff --git a/tcg/sparc/tcg-target.c.inc b/tcg/sparc/tcg-target.c.inc
> > index 6775bd30fc..af97cbdeef 100644
> > --- a/tcg/sparc/tcg-target.c.inc
> > +++ b/tcg/sparc/tcg-target.c.inc
> > @@ -291,14 +291,14 @@ static inline int check_fit_i32(int32_t val, unsigned 
> > int bits)
> > # define check_fit_ptr  check_fit_i32
> > #endif
> >
> > -static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
> > +static bool patch_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type,
> >                         intptr_t value, intptr_t addend)
> > {
> >     uint32_t insn = *code_ptr;
> >     intptr_t pcrel;
> >
> >     value += addend;
> > -    pcrel = tcg_ptr_byte_diff((tcg_insn_unit *)value, code_ptr);
> > +    pcrel = tcg_ptr_byte_diff((const tcg_insn_unit *)value, code_ptr);
> >
> >     switch (type) {
> >     case R_SPARC_WDISP16:
> > @@ -840,7 +840,7 @@ static void tcg_out_addsub2_i64(TCGContext *s, TCGReg 
> > rl, TCGReg rh,
> >     tcg_out_mov(s, TCG_TYPE_I64, rl, tmp);
> > }
> >
> > -static void tcg_out_call_nodelay(TCGContext *s, tcg_insn_unit *dest,
> > +static void tcg_out_call_nodelay(TCGContext *s, const tcg_insn_unit *dest,
> >                                  bool in_prologue)
> > {
> >     ptrdiff_t disp = tcg_pcrel_diff(s, dest);
> > @@ -855,7 +855,7 @@ static void tcg_out_call_nodelay(TCGContext *s, 
> > tcg_insn_unit *dest,
> >     }
> > }
> >
> > -static void tcg_out_call(TCGContext *s, tcg_insn_unit *dest)
> > +static void tcg_out_call(TCGContext *s, const tcg_insn_unit *dest)
> > {
> >     tcg_out_call_nodelay(s, dest, false);
> >     tcg_out_nop(s);
> > @@ -868,8 +868,8 @@ static void tcg_out_mb(TCGContext *s, TCGArg a0)
> > }
> >
> > #ifdef CONFIG_SOFTMMU
> > -static tcg_insn_unit *qemu_ld_trampoline[16];
> > -static tcg_insn_unit *qemu_st_trampoline[16];
> > +static const tcg_insn_unit *qemu_ld_trampoline[16];
> > +static const tcg_insn_unit *qemu_st_trampoline[16];
> >
> > static void emit_extend(TCGContext *s, TCGReg r, int op)
> > {
> > @@ -1048,11 +1048,11 @@ static void tcg_target_qemu_prologue(TCGContext *s)
> > #endif
> > }
> >
> > -static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
> > +static void tcg_out_nop_fill(TCGContext *s, tcg_insn_unit *p, int count)
> > {
> >     int i;
> >     for (i = 0; i < count; ++i) {
> > -        p[i] = NOP;
> > +        (TCG_CODE_PTR_RW(s, p))[i] = NOP;
> >     }
> > }
> >
> > @@ -1163,7 +1163,7 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg 
> > data, TCGReg addr,
> > #ifdef CONFIG_SOFTMMU
> >     unsigned memi = get_mmuidx(oi);
> >     TCGReg addrz, param;
> > -    tcg_insn_unit *func;
> > +    const tcg_insn_unit *func;
> >     tcg_insn_unit *label_ptr;
> >
> >     addrz = tcg_out_tlb_load(s, addr, memi, memop,
> > @@ -1226,7 +1226,8 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg 
> > data, TCGReg addr,
> >         }
> >     }
> >
> > -    *label_ptr |= INSN_OFF19(tcg_ptr_byte_diff(s->code_ptr, label_ptr));
> > +    *TCG_CODE_PTR_RW(s, label_ptr) |=
> > +        INSN_OFF19(tcg_ptr_byte_diff(s->code_ptr, label_ptr));
> > #else
> >     if (SPARC64 && TARGET_LONG_BITS == 32) {
> >         tcg_out_arithi(s, TCG_REG_T1, addr, 0, SHIFT_SRL);
> > @@ -1822,7 +1823,7 @@ void tcg_register_jit(void *buf, size_t buf_size)
> > }
> >
> > void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr,
> > -                              uintptr_t addr)
> > +                              uintptr_t addr, uintptr_t wr_addr)
> > {
> >     intptr_t tb_disp = addr - tc_ptr;
> >     intptr_t br_disp = addr - jmp_addr;
> > @@ -1834,8 +1835,11 @@ void tb_target_set_jmp_target(uintptr_t tc_ptr, 
> > uintptr_t jmp_addr,
> >     tcg_debug_assert(br_disp == (int32_t)br_disp);
> >
> >     if (!USE_REG_TB) {
> > -        qatomic_set((uint32_t *)jmp_addr,
> > +        qatomic_set((uint32_t *)wr_addr,
> >                   deposit32(CALL, 0, 30, br_disp >> 2));
> > +#if defined(CONFIG_IOS_JIT)
> > +        flush_dcache_range(wr_addr, wr_addr + 4);
> > +#endif
> >         flush_icache_range(jmp_addr, jmp_addr + 4);
> >         return;
> >     }
> > @@ -1859,6 +1863,9 @@ void tb_target_set_jmp_target(uintptr_t tc_ptr, 
> > uintptr_t jmp_addr,
> >               | INSN_IMM13((tb_disp & 0x3ff) | -0x400));
> >     }
> >
> > -    qatomic_set((uint64_t *)jmp_addr, deposit64(i2, 32, 32, i1));
> > +    qatomic_set((uint64_t *)wr_addr, deposit64(i2, 32, 32, i1));
> > +#if defined(CONFIG_IOS_JIT)
> > +    flush_dcache_range(wr_addr, wr_addr + 8);
> > +#endif
> >     flush_icache_range(jmp_addr, jmp_addr + 8);
> > }
> > diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
> > index 633841ebf2..d102e13692 100644
> > --- a/tcg/sparc/tcg-target.h
> > +++ b/tcg/sparc/tcg-target.h
> > @@ -176,7 +176,13 @@ static inline void flush_icache_range(uintptr_t start, 
> > uintptr_t stop)
> >     }
> > }
> >
> > -void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
> > +void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
> > +#if defined(CONFIG_IOS_JIT)
> > +static inline void flush_dcache_range(uintptr_t start, uintptr_t stop)
> > +{
> > +#error "Unimplemented dcache flush function"
> > +}
> > +#endif
> >
> > #define TCG_TARGET_NEED_POOL_LABELS
> >
> > diff --git a/tcg/tcg-ldst.c.inc b/tcg/tcg-ldst.c.inc
> > index 05f9b3ccd6..eaba08700e 100644
> > --- a/tcg/tcg-ldst.c.inc
> > +++ b/tcg/tcg-ldst.c.inc
> > @@ -28,7 +28,7 @@ typedef struct TCGLabelQemuLdst {
> >     TCGReg addrhi_reg;      /* reg index for high word of guest virtual 
> > addr */
> >     TCGReg datalo_reg;      /* reg index for low word to be loaded or 
> > stored */
> >     TCGReg datahi_reg;      /* reg index for high word to be loaded or 
> > stored */
> > -    tcg_insn_unit *raddr;   /* gen code addr of the next IR of qemu_ld/st 
> > IR */
> > +    const tcg_insn_unit *raddr; /* gen code addr of the next IR of 
> > qemu_ld/st */
> >     tcg_insn_unit *label_ptr[2]; /* label pointers to be updated */
> >     QSIMPLEQ_ENTRY(TCGLabelQemuLdst) next;
> > } TCGLabelQemuLdst;
> > diff --git a/tcg/tcg-pool.c.inc b/tcg/tcg-pool.c.inc
> > index 82cbcc89bd..97bb90b7cc 100644
> > --- a/tcg/tcg-pool.c.inc
> > +++ b/tcg/tcg-pool.c.inc
> > @@ -119,7 +119,7 @@ static inline void new_pool_l8(TCGContext *s, int 
> > rtype, tcg_insn_unit *label,
> > }
> >
> > /* To be provided by cpu/tcg-target.c.inc.  */
> > -static void tcg_out_nop_fill(tcg_insn_unit *p, int count);
> > +static void tcg_out_nop_fill(TCGContext *s, tcg_insn_unit *p, int count);
> >
> > static int tcg_out_pool_finalize(TCGContext *s)
> > {
> > @@ -135,7 +135,7 @@ static int tcg_out_pool_finalize(TCGContext *s)
> >        again when allocating the next TranslationBlock structure.  */
> >     a = (void *)ROUND_UP((uintptr_t)s->code_ptr,
> >                          sizeof(tcg_target_ulong) * p->nlong);
> > -    tcg_out_nop_fill(s->code_ptr, (tcg_insn_unit *)a - s->code_ptr);
> > +    tcg_out_nop_fill(s, s->code_ptr, (tcg_insn_unit *)a - s->code_ptr);
> >     s->data_gen_ptr = a;
> >
> >     for (; p != NULL; p = p->next) {
> > @@ -144,11 +144,12 @@ static int tcg_out_pool_finalize(TCGContext *s)
> >             if (unlikely(a > s->code_gen_highwater)) {
> >                 return -1;
> >             }
> > -            memcpy(a, p->data, size);
> > +            memcpy(TCG_CODE_PTR_RW(s, a), p->data, size);
> >             a += size;
> >             l = p;
> >         }
> > -        if (!patch_reloc(p->label, p->rtype, (intptr_t)a - size, 
> > p->addend)) {
> > +        if (!patch_reloc(s, p->label, p->rtype,
> > +                         (intptr_t)a - size, p->addend)) {
> >             return -2;
> >         }
> >     }
> > diff --git a/tcg/tcg.c b/tcg/tcg.c
> > index a8c28440e2..ef203a34a6 100644
> > --- a/tcg/tcg.c
> > +++ b/tcg/tcg.c
> > @@ -70,7 +70,7 @@
> > static void tcg_target_init(TCGContext *s);
> > static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode);
> > static void tcg_target_qemu_prologue(TCGContext *s);
> > -static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
> > +static bool patch_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type,
> >                         intptr_t value, intptr_t addend);
> >
> > /* The CIE and FDE header definitions will be common to all hosts.  */
> > @@ -148,7 +148,7 @@ static void tcg_out_st(TCGContext *s, TCGType type, 
> > TCGReg arg, TCGReg arg1,
> >                        intptr_t arg2);
> > static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
> >                         TCGReg base, intptr_t ofs);
> > -static void tcg_out_call(TCGContext *s, tcg_insn_unit *target);
> > +static void tcg_out_call(TCGContext *s, const tcg_insn_unit *target);
> > static int tcg_target_const_match(tcg_target_long val, TCGType type,
> >                                   const TCGArgConstraint *arg_ct);
> > #ifdef TCG_TARGET_NEED_LDST_LABELS
> > @@ -203,13 +203,15 @@ static TCGRegSet tcg_target_call_clobber_regs;
> > #if TCG_TARGET_INSN_UNIT_SIZE == 1
> > static __attribute__((unused)) inline void tcg_out8(TCGContext *s, uint8_t 
> > v)
> > {
> > -    *s->code_ptr++ = v;
> > +    *TCG_CODE_PTR_RW(s, s->code_ptr) = v;
> > +    s->code_ptr++;
> > }
> >
> > -static __attribute__((unused)) inline void tcg_patch8(tcg_insn_unit *p,
> > +static __attribute__((unused)) inline void tcg_patch8(TCGContext *s,
> > +                                                      tcg_insn_unit *p,
> >                                                       uint8_t v)
> > {
> > -    *p = v;
> > +    *TCG_CODE_PTR_RW(s, p) = v;
> > }
> > #endif
> >
> > @@ -217,21 +219,23 @@ static __attribute__((unused)) inline void 
> > tcg_patch8(tcg_insn_unit *p,
> > static __attribute__((unused)) inline void tcg_out16(TCGContext *s, 
> > uint16_t v)
> > {
> >     if (TCG_TARGET_INSN_UNIT_SIZE == 2) {
> > -        *s->code_ptr++ = v;
> > +        *TCG_CODE_PTR_RW(s, s->code_ptr) = v;
> > +        s->code_ptr++;
> >     } else {
> >         tcg_insn_unit *p = s->code_ptr;
> > -        memcpy(p, &v, sizeof(v));
> > +        memcpy(TCG_CODE_PTR_RW(s, p), &v, sizeof(v));
> >         s->code_ptr = p + (2 / TCG_TARGET_INSN_UNIT_SIZE);
> >     }
> > }
> >
> > -static __attribute__((unused)) inline void tcg_patch16(tcg_insn_unit *p,
> > +static __attribute__((unused)) inline void tcg_patch16(TCGContext *s,
> > +                                                       tcg_insn_unit *p,
> >                                                        uint16_t v)
> > {
> >     if (TCG_TARGET_INSN_UNIT_SIZE == 2) {
> > -        *p = v;
> > +        *TCG_CODE_PTR_RW(s, p) = v;
> >     } else {
> > -        memcpy(p, &v, sizeof(v));
> > +        memcpy(TCG_CODE_PTR_RW(s, p), &v, sizeof(v));
> >     }
> > }
> > #endif
> > @@ -240,21 +244,23 @@ static __attribute__((unused)) inline void 
> > tcg_patch16(tcg_insn_unit *p,
> > static __attribute__((unused)) inline void tcg_out32(TCGContext *s, 
> > uint32_t v)
> > {
> >     if (TCG_TARGET_INSN_UNIT_SIZE == 4) {
> > -        *s->code_ptr++ = v;
> > +        *TCG_CODE_PTR_RW(s, s->code_ptr) = v;
> > +        s->code_ptr++;
> >     } else {
> >         tcg_insn_unit *p = s->code_ptr;
> > -        memcpy(p, &v, sizeof(v));
> > +        memcpy(TCG_CODE_PTR_RW(s, p), &v, sizeof(v));
> >         s->code_ptr = p + (4 / TCG_TARGET_INSN_UNIT_SIZE);
> >     }
> > }
> >
> > -static __attribute__((unused)) inline void tcg_patch32(tcg_insn_unit *p,
> > +static __attribute__((unused)) inline void tcg_patch32(TCGContext *s,
> > +                                                       tcg_insn_unit *p,
> >                                                        uint32_t v)
> > {
> >     if (TCG_TARGET_INSN_UNIT_SIZE == 4) {
> >         *p = v;
> >     } else {
> > -        memcpy(p, &v, sizeof(v));
> > +        memcpy(TCG_CODE_PTR_RW(s, p), &v, sizeof(v));
> >     }
> > }
> > #endif
> > @@ -263,21 +269,23 @@ static __attribute__((unused)) inline void 
> > tcg_patch32(tcg_insn_unit *p,
> > static __attribute__((unused)) inline void tcg_out64(TCGContext *s, 
> > uint64_t v)
> > {
> >     if (TCG_TARGET_INSN_UNIT_SIZE == 8) {
> > -        *s->code_ptr++ = v;
> > +        *TCG_CODE_PTR_RW(s, s->code_ptr) = v;
> > +        s->code_ptr++;
> >     } else {
> >         tcg_insn_unit *p = s->code_ptr;
> > -        memcpy(p, &v, sizeof(v));
> > +        memcpy(TCG_CODE_PTR_RW(s, p), &v, sizeof(v));
> >         s->code_ptr = p + (8 / TCG_TARGET_INSN_UNIT_SIZE);
> >     }
> > }
> >
> > -static __attribute__((unused)) inline void tcg_patch64(tcg_insn_unit *p,
> > +static __attribute__((unused)) inline void tcg_patch64(TCGContext *s,
> > +                                                       tcg_insn_unit *p,
> >                                                        uint64_t v)
> > {
> >     if (TCG_TARGET_INSN_UNIT_SIZE == 8) {
> >         *p = v;
> >     } else {
> > -        memcpy(p, &v, sizeof(v));
> > +        memcpy(TCG_CODE_PTR_RW(s, p), &v, sizeof(v));
> >     }
> > }
> > #endif
> > @@ -295,7 +303,7 @@ static void tcg_out_reloc(TCGContext *s, tcg_insn_unit 
> > *code_ptr, int type,
> >     QSIMPLEQ_INSERT_TAIL(&l->relocs, r, next);
> > }
> >
> > -static void tcg_out_label(TCGContext *s, TCGLabel *l, tcg_insn_unit *ptr)
> > +static void tcg_out_label(TCGContext *s, TCGLabel *l, const tcg_insn_unit 
> > *ptr)
> > {
> >     tcg_debug_assert(!l->has_value);
> >     l->has_value = 1;
> > @@ -325,7 +333,7 @@ static bool tcg_resolve_relocs(TCGContext *s)
> >         uintptr_t value = l->u.value;
> >
> >         QSIMPLEQ_FOREACH(r, &l->relocs, next) {
> > -            if (!patch_reloc(r->ptr, r->type, value, r->addend)) {
> > +            if (!patch_reloc(s, r->ptr, r->type, value, r->addend)) {
> >                 return false;
> >             }
> >         }
> > @@ -1039,7 +1047,7 @@ TranslationBlock *tcg_tb_alloc(TCGContext *s)
> >     }
> >     qatomic_set(&s->code_gen_ptr, next);
> >     s->data_gen_ptr = NULL;
> > -    return tb;
> > +    return (TranslationBlock *)TCG_CODE_PTR_RW(s, tb);
> > }
> >
> > void tcg_prologue_init(TCGContext *s)
> > @@ -1076,6 +1084,10 @@ void tcg_prologue_init(TCGContext *s)
> > #endif
> >
> >     buf1 = s->code_ptr;
> > +#if defined(CONFIG_IOS_JIT)
> > +    flush_dcache_range((uintptr_t)TCG_CODE_PTR_RW(s, buf0),
> > +                       (uintptr_t)TCG_CODE_PTR_RW(s, buf1));
> > +#endif
> >     flush_icache_range((uintptr_t)buf0, (uintptr_t)buf1);
> >
> >     /* Deduct the prologue from the buffer.  */
> > @@ -4267,6 +4279,12 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
> >         return -2;
> >     }
> >
> > +#if defined(CONFIG_IOS_JIT)
> > +    /* flush data cache on mirror */
> > +    flush_dcache_range((uintptr_t)TCG_CODE_PTR_RW(s, s->code_buf),
> > +                       (uintptr_t)TCG_CODE_PTR_RW(s, s->code_ptr));
> > +#endif
> > +
> >     /* flush instruction cache */
> >     flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr);
> >
> > diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
> > index 231b9b1775..133213be3a 100644
> > --- a/tcg/tci/tcg-target.c.inc
> > +++ b/tcg/tci/tcg-target.c.inc
> > @@ -369,7 +369,7 @@ static const char *const 
> > tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
> > };
> > #endif
> >
> > -static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
> > +static bool patch_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type,
> >                         intptr_t value, intptr_t addend)
> > {
> >     /* tcg_out_reloc always uses the same type, addend. */
> > @@ -377,9 +377,9 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int 
> > type,
> >     tcg_debug_assert(addend == 0);
> >     tcg_debug_assert(value != 0);
> >     if (TCG_TARGET_REG_BITS == 32) {
> > -        tcg_patch32(code_ptr, value);
> > +        tcg_patch32(s, code_ptr, value);
> >     } else {
> > -        tcg_patch64(code_ptr, value);
> > +        tcg_patch64(s, code_ptr, value);
> >     }
> >     return true;
> > }
> > @@ -545,7 +545,7 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
> >     old_code_ptr[1] = s->code_ptr - old_code_ptr;
> > }
> >
> > -static inline void tcg_out_call(TCGContext *s, tcg_insn_unit *arg)
> > +static inline void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg)
> > {
> >     uint8_t *old_code_ptr = s->code_ptr;
> >     tcg_out_op_t(s, INDEX_op_call);
> > diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
> > index 8c1c1d265d..2a258ea350 100644
> > --- a/tcg/tci/tcg-target.h
> > +++ b/tcg/tci/tcg-target.h
> > @@ -195,6 +195,12 @@ static inline void flush_icache_range(uintptr_t start, 
> > uintptr_t stop)
> > {
> > }
> >
> > +#if defined(CONFIG_IOS_JIT)
> > +static inline void flush_dcache_range(uintptr_t start, uintptr_t stop)
> > +{
> > +}
> > +#endif
> > +
> > /* We could notice __i386__ or __s390x__ and reduce the barriers depending
> >    on the host.  But if you want performance, you use the normal backend.
> >    We prefer consistency across hosts on this.  */
> > @@ -203,7 +209,8 @@ static inline void flush_icache_range(uintptr_t start, 
> > uintptr_t stop)
> > #define TCG_TARGET_HAS_MEMORY_BSWAP     1
> >
> > static inline void tb_target_set_jmp_target(uintptr_t tc_ptr,
> > -                                            uintptr_t jmp_addr, uintptr_t 
> > addr)
> > +                                            uintptr_t jmp_addr, uintptr_t 
> > addr,
> > +                                            uintptr_t wr_addr)
> > {
> >     /* patch the branch destination */
> >     qatomic_set((int32_t *)jmp_addr, addr - (jmp_addr + 4));
> >
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]