On 08/08/2017 03:44 AM, Peter Maydell wrote:
> QEMU has a wide selection of different functions for doing
> loads and stores; provide some overview documentation of
> what they do and how to pick which one to use.
> 
> Signed-off-by: Peter Maydell <peter.mayd...@linaro.org>
> ---
> This is currently a work in progress, with many TODO points.
> Some of the formatting is a bit inconsistent from section to
> section. I post it to see if people think it's a useful
> document to have and to try to get some answers to the TODO
> points which are "I don't know why this function exists" and
> "when should we use this function rather than that other one"...
> 
>  docs/devel/loads-stores.rst | 365 
> ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 365 insertions(+)
>  create mode 100644 docs/devel/loads-stores.rst
> 
> diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
> new file mode 100644
> index 0000000..73ae4c8
> --- /dev/null
> +++ b/docs/devel/loads-stores.rst
> @@ -0,0 +1,365 @@
> +..
> +   Copyright (c) 2017 Linaro Limited
> +   Written by Peter Maydell
> +   TODO: do we have a standard doc license? bitmaps.rst
> +   uses the FreeBSD documentation license, I notice.
> +
> +===================
> +Load and Store APIs
> +===================
> +
> +QEMU internally has multiple families of functions for performing
> +loads and stores. This document attempts to enumerate them all
> +and indicate when to use them. It does not provide detailed
> +documentation of each API -- for that you should look at the
> +documentation comments in the relevant header files.
> +
> +
> +``ld*_p and st_*p``
> +~~~~~~~~~~~~~~~~~~~
> +
> +These functions operate on a host pointer, and should be used
> +when you already have a pointer into host memory (corresponding
> +to guest ram or a local buffer). They deal with doing accesses
> +with the desired endianness and with correctly handling
> +potentially unaligned pointer values.
> +
> +Function names follow the pattern:
> +
> +load: ``ld{type}{sign}{size}_{endian}_p(ptr)``
> +
> +store: ``st{type}{size}_{endian}_p(ptr, val)``
> +
> +``type``
> + - (empty) : integer access
> + - ``f`` : float access
> +
> +``sign``
> + - (empty) : for 32 or 64 bit sizes (including floats and doubles)
> + - ``u`` : unsigned
> + - ``s`` : signed
> +
> +``size``
> + - ``b`` : 8 bits
> + - ``w`` : 16 bits
> + - ``l`` : 32 bits
> + - ``q`` : 64 bits
> +
> +``endian``
> + - ``he`` : host endian
> + - ``be`` : big endian
> + - ``le`` : little endian
> +
> +(except for byte accesses, which have no endian infix).
> +
> +The ``_{endian}`` infix is omitted for target-endian accesses.
> +
> +The target endian accessors are only available to source
> +files which are built per-target.
> +
> +Regexes for git grep
> + - ``\<ldf\?[us]\?[bwlq]\(_[hbl]e\)\?_p\>``
> + - ``\<stf\?[bwlq]\(_[hbl]e\)\?_p\>``
> +
> +``cpu_{ld,st}_*``
> +~~~~~~~~~~~~~~~~~
> +
> +These functions operate on a guest virtual address. Be aware
> +that these functions may cause a guest CPU exception to be
> +taken (eg for an alignment fault or MMU fault) which will
> +result in guest CPU state being updated and control longjumping
> +out of the function call. They should therefore only be used
> +in code that is implementing emulation of the target CPU.
> +
> +Function names follow the pattern:
> +
> +load: ``cpu_ld{sign}{size}_{mmusuffix}(env, ptr)``
> +
> +store: ``cpu_st{size}_{mmusuffix}(env, ptr, val)``
> +
> +``sign``
> + - (empty) : for 32 or 64 bit sizes
> + - ``u`` : unsigned
> + - ``s`` : signed
> +
> +``size``
> + - ``b`` : 8 bits
> + - ``w`` : 16 bits
> + - ``l`` : 32 bits
> + - ``q`` : 64 bits
> +
> +``mmusuffix`` is one of the generic suffixes ``data`` or ``code``, or
> +(for softmmu configs) a target-specific MMU mode suffix as defined
> +in the target's ``cpu.h``.

On memory faults, these functions will not do any unwinding.  So the cpu state
most have been saved by the translator before calling a helper that uses these.


> +
> +Regexes for git grep
> + - ``\<cpu_ld[us]\?[bwlq]_[a-zA-Z0-9]\+\>``
> + - ``\<cpu_st[bwlq]_[a-zA-Z0-9]\+\>``
> +
> +``cpu_{ld,st}_*_ra``
> +~~~~~~~~~~~~~~~~~~~~
> +
> +Thes functions work like the ``cpu_{ld,st}_*`` functions except
> +that they also take a ``retaddr`` argument.
> +
> +**TODO**: when should these be used and what should ``retaddr`` be?

retaddr should be GETPC() called directly from a HELPER(foo), so that it
computes the return address into code_gen_buffer.  retaddr will be used to
unwind the cpu state, and so the translator need not have done any extra saving
before calling the helper.

I would say that these functions should preferentially be used with all new 
code.


> +
> +Function names follow the pattern:
> +
> +load: ``cpu_ld{sign}{size}_{mmusuffix}_ra(env, ptr, retaddr)``
> +
> +store: ``cpu_st{sign}{size}_{mmusuffix}_ra(env, ptr, val, retaddr)``
> +
> +Regexes for git grep
> + - ``\<cpu_ld[us]\?[bwlq]_[a-zA-Z0-9]\+_ra\>``
> + - ``\<cpu_st[bwlq]_[a-zA-Z0-9]\+_ra\>``
> +
> +``helper_*_{ld,st}*mmu``
> +~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +These functions are intended primarily to be called by the code
> +generated by the TCG backend. They may also be called by target
> +CPU helper function code. (XXX why, and when this vs cpu_{ld,st}_* ?)

Because cpu_{ld,st}_* infer a mmu_idx from the name + cpu_mmu_index, whereas
these functions take it as a parameter.

> +
> +**TODO** tcg.h claims the target-endian helper_ret* are temporary and
> +will go away?

Heh.  Yes.  Except that the usage within the target front-end helpers got in
the way.  The tcg backends were all converted to explicit endianness, but the
front ends did want a convenient target-endian name.  I suppose we could rename
"ret" to "te" or something, or just remove the comment...

> +
> +**TODO** why is "target endian" "ret" anyway?

"ret" was added simply to indicate that these functions take a "retaddr", as
opposed to the oldest iteration of these functions that did not.  It was the
third iteration that added "le"/"be".


r~

Reply via email to