qemu/include/exec/memop.h
<<
>>
Prefs
   1/*
   2 * Constants for memory operations
   3 *
   4 * Authors:
   5 *  Richard Henderson <rth@twiddle.net>
   6 *
   7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
   8 * See the COPYING file in the top-level directory.
   9 *
  10 */
  11
  12#ifndef MEMOP_H
  13#define MEMOP_H
  14
  15#include "qemu/host-utils.h"
  16
  17typedef enum MemOp {
  18    MO_8     = 0,
  19    MO_16    = 1,
  20    MO_32    = 2,
  21    MO_64    = 3,
  22    MO_128   = 4,
  23    MO_256   = 5,
  24    MO_512   = 6,
  25    MO_1024  = 7,
  26    MO_SIZE  = 0x07,   /* Mask for the above.  */
  27
  28    MO_SIGN  = 0x08,   /* Sign-extended, otherwise zero-extended.  */
  29
  30    MO_BSWAP = 0x10,   /* Host reverse endian.  */
  31#if HOST_BIG_ENDIAN
  32    MO_LE    = MO_BSWAP,
  33    MO_BE    = 0,
  34#else
  35    MO_LE    = 0,
  36    MO_BE    = MO_BSWAP,
  37#endif
  38#ifdef NEED_CPU_H
  39#if TARGET_BIG_ENDIAN
  40    MO_TE    = MO_BE,
  41#else
  42    MO_TE    = MO_LE,
  43#endif
  44#endif
  45
  46    /*
  47     * MO_UNALN accesses are never checked for alignment.
  48     * MO_ALIGN accesses will result in a call to the CPU's
  49     * do_unaligned_access hook if the guest address is not aligned.
  50     * The default depends on whether the target CPU defines
  51     * TARGET_ALIGNED_ONLY.
  52     *
  53     * Some architectures (e.g. ARMv8) need the address which is aligned
  54     * to a size more than the size of the memory access.
  55     * Some architectures (e.g. SPARCv9) need an address which is aligned,
  56     * but less strictly than the natural alignment.
  57     *
  58     * MO_ALIGN supposes the alignment size is the size of a memory access.
  59     *
  60     * There are three options:
  61     * - unaligned access permitted (MO_UNALN).
  62     * - an alignment to the size of an access (MO_ALIGN);
  63     * - an alignment to a specified size, which may be more or less than
  64     *   the access size (MO_ALIGN_x where 'x' is a size in bytes);
  65     */
  66    MO_ASHIFT = 5,
  67    MO_AMASK = 0x7 << MO_ASHIFT,
  68#ifdef NEED_CPU_H
  69#ifdef TARGET_ALIGNED_ONLY
  70    MO_ALIGN = 0,
  71    MO_UNALN = MO_AMASK,
  72#else
  73    MO_ALIGN = MO_AMASK,
  74    MO_UNALN = 0,
  75#endif
  76#endif
  77    MO_ALIGN_2  = 1 << MO_ASHIFT,
  78    MO_ALIGN_4  = 2 << MO_ASHIFT,
  79    MO_ALIGN_8  = 3 << MO_ASHIFT,
  80    MO_ALIGN_16 = 4 << MO_ASHIFT,
  81    MO_ALIGN_32 = 5 << MO_ASHIFT,
  82    MO_ALIGN_64 = 6 << MO_ASHIFT,
  83
  84    /* Combinations of the above, for ease of use.  */
  85    MO_UB    = MO_8,
  86    MO_UW    = MO_16,
  87    MO_UL    = MO_32,
  88    MO_UQ    = MO_64,
  89    MO_UO    = MO_128,
  90    MO_SB    = MO_SIGN | MO_8,
  91    MO_SW    = MO_SIGN | MO_16,
  92    MO_SL    = MO_SIGN | MO_32,
  93    MO_SQ    = MO_SIGN | MO_64,
  94    MO_SO    = MO_SIGN | MO_128,
  95
  96    MO_LEUW  = MO_LE | MO_UW,
  97    MO_LEUL  = MO_LE | MO_UL,
  98    MO_LEUQ  = MO_LE | MO_UQ,
  99    MO_LESW  = MO_LE | MO_SW,
 100    MO_LESL  = MO_LE | MO_SL,
 101    MO_LESQ  = MO_LE | MO_SQ,
 102
 103    MO_BEUW  = MO_BE | MO_UW,
 104    MO_BEUL  = MO_BE | MO_UL,
 105    MO_BEUQ  = MO_BE | MO_UQ,
 106    MO_BESW  = MO_BE | MO_SW,
 107    MO_BESL  = MO_BE | MO_SL,
 108    MO_BESQ  = MO_BE | MO_SQ,
 109
 110#ifdef NEED_CPU_H
 111    MO_TEUW  = MO_TE | MO_UW,
 112    MO_TEUL  = MO_TE | MO_UL,
 113    MO_TEUQ  = MO_TE | MO_UQ,
 114    MO_TEUO  = MO_TE | MO_UO,
 115    MO_TESW  = MO_TE | MO_SW,
 116    MO_TESL  = MO_TE | MO_SL,
 117    MO_TESQ  = MO_TE | MO_SQ,
 118#endif
 119
 120    MO_SSIZE = MO_SIZE | MO_SIGN,
 121} MemOp;
 122
 123/* MemOp to size in bytes.  */
 124static inline unsigned memop_size(MemOp op)
 125{
 126    return 1 << (op & MO_SIZE);
 127}
 128
 129/* Size in bytes to MemOp.  */
 130static inline MemOp size_memop(unsigned size)
 131{
 132#ifdef CONFIG_DEBUG_TCG
 133    /* Power of 2 up to 8.  */
 134    assert((size & (size - 1)) == 0 && size >= 1 && size <= 8);
 135#endif
 136    return ctz32(size);
 137}
 138
 139/* Big endianness from MemOp.  */
 140static inline bool memop_big_endian(MemOp op)
 141{
 142    return (op & MO_BSWAP) == MO_BE;
 143}
 144
 145#endif
 146