On Fri, 5 Dec 2025 at 14:27, Shusaku KURAMITSU
<[email protected]> wrote:
> I've noticed a possible discrepancy between the comment and the behavior
>
> of i386's prepare_host_addr (located at tcg/i386/tcg-target.c.inc, line
> 2157-2260):
>
>
> ```
>
> /*
> * For softmmu, perform the TLB load and compare.
> * For useronly, perform any required alignment tests.
> * In both cases, return a TCGLabelQemuLdst structure if the slow path
> * is required and fill in @h with the host address for the fast path.
> */
> static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
> TCGReg addr, MemOpIdx oi,
> bool is_ld)
> {
> TCGLabelQemuLdst *ldst = NULL;
>
> ...
> if (tcg_use_softmmu) {
>
> ...
>
> ldst = new_ldst_label(s);
> ldst->is_ld = is_ld;
> ldst->oi = oi;
> ldst->addr_reg = addr;
>
> ...
>
> } else if (a_mask) {
> ...
> }
>
> return ldst;
> }
>
> ```
>
>
> The code appears to always assign (in case of softmmu) a label to `ldst`
> and return it,
No; if tcg_use_softmmu is false and a_mask is zero then
we will not take either the if() or the else if() block,
and ldst will still be NULL when we return it.
This is because:
* softmmu always requires a slowpath (because we might
look the guest address up in the TLB but not find it)
* linux-user mode needs a slowpath only if we need to
enforce alignment and atomicity checks for this
memory access (because linux-user always has "guest
address == host address + some constant", so most
simple loads and stores cannot fail or be complicated)
If we don't have to do either, then we don't need the slowpath.
> As I understand it, there is no way to determine, at this point, which
> of the two paths to use;
>
> the generated machine code (see L2233-2237), not the C code here,
> performs the TLB comparison.
That's right. We are generating the code in this function
to do everything except the final "load/store from the host
address" part. If we're using softmmu that includes all the
code to look the guest address up in the TLB.
I think the way to understand this function is to look at
the functions that call it, like tgen_qemu_ld(). They do:
* call prepare_host_addr()
* call a function to generate a plain host load or store
If the prepare_host_addr() code wants to do an out of
line slow-path, then the code we emit looks like:
- do stuff to figure out if we can fast path this
- conditional jump to out-of-line label for slow path
- fast path handling; at the end of this we have the
host address for the memory access
- host load or store generated by tgen_qemu_ld etc
- and then fall through into code for the next guest insn
At the end of the TB we will arrange to emit the
out-of-line label and the slow path code.
thanks
-- PMM