123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- /*
- * Constants for memory operations
- *
- * Authors:
- * Richard Henderson <rth@twiddle.net>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
- #ifndef MEMOP_H
- #define MEMOP_H
- #include "qemu/host-utils.h"
- typedef enum MemOp {
- MO_8 = 0,
- MO_16 = 1,
- MO_32 = 2,
- MO_64 = 3,
- MO_128 = 4,
- MO_256 = 5,
- MO_512 = 6,
- MO_1024 = 7,
- MO_SIZE = 0x07, /* Mask for the above. */
- MO_SIGN = 0x08, /* Sign-extended, otherwise zero-extended. */
- MO_BSWAP = 0x10, /* Host reverse endian. */
- #if HOST_BIG_ENDIAN
- MO_LE = MO_BSWAP,
- MO_BE = 0,
- #else
- MO_LE = 0,
- MO_BE = MO_BSWAP,
- #endif
- #ifdef COMPILING_PER_TARGET
- #if TARGET_BIG_ENDIAN
- MO_TE = MO_BE,
- #else
- MO_TE = MO_LE,
- #endif
- #endif
- /*
- * MO_UNALN accesses are never checked for alignment.
- * MO_ALIGN accesses will result in a call to the CPU's
- * do_unaligned_access hook if the guest address is not aligned.
- *
- * Some architectures (e.g. ARMv8) need the address which is aligned
- * to a size more than the size of the memory access.
- * Some architectures (e.g. SPARCv9) need an address which is aligned,
- * but less strictly than the natural alignment.
- *
- * MO_ALIGN supposes the alignment size is the size of a memory access.
- *
- * There are three options:
- * - unaligned access permitted (MO_UNALN).
- * - an alignment to the size of an access (MO_ALIGN);
- * - an alignment to a specified size, which may be more or less than
- * the access size (MO_ALIGN_x where 'x' is a size in bytes);
- */
- MO_ASHIFT = 5,
- MO_AMASK = 0x7 << MO_ASHIFT,
- MO_UNALN = 0,
- MO_ALIGN_2 = 1 << MO_ASHIFT,
- MO_ALIGN_4 = 2 << MO_ASHIFT,
- MO_ALIGN_8 = 3 << MO_ASHIFT,
- MO_ALIGN_16 = 4 << MO_ASHIFT,
- MO_ALIGN_32 = 5 << MO_ASHIFT,
- MO_ALIGN_64 = 6 << MO_ASHIFT,
- MO_ALIGN = MO_AMASK,
- /*
- * MO_ATOM_* describes the atomicity requirements of the operation:
- * MO_ATOM_IFALIGN: the operation must be single-copy atomic if it
- * is aligned; if unaligned there is no atomicity.
- * MO_ATOM_IFALIGN_PAIR: the entire operation may be considered to
- * be a pair of half-sized operations which are packed together
- * for convenience, with single-copy atomicity on each half if
- * the half is aligned.
- * This is the atomicity e.g. of Arm pre-FEAT_LSE2 LDP.
- * MO_ATOM_WITHIN16: the operation is single-copy atomic, even if it
- * is unaligned, so long as it does not cross a 16-byte boundary;
- * if it crosses a 16-byte boundary there is no atomicity.
- * This is the atomicity e.g. of Arm FEAT_LSE2 LDR.
- * MO_ATOM_WITHIN16_PAIR: the entire operation is single-copy atomic,
- * if it happens to be within a 16-byte boundary, otherwise it
- * devolves to a pair of half-sized MO_ATOM_WITHIN16 operations.
- * Depending on alignment, one or both will be single-copy atomic.
- * This is the atomicity e.g. of Arm FEAT_LSE2 LDP.
- * MO_ATOM_SUBALIGN: the operation is single-copy atomic by parts
- * by the alignment. E.g. if an 8-byte value is accessed at an
- * address which is 0 mod 8, then the whole 8-byte access is
- * single-copy atomic; otherwise, if it is accessed at 0 mod 4
- * then each 4-byte subobject is single-copy atomic; otherwise
- * if it is accessed at 0 mod 2 then the four 2-byte subobjects
- * are single-copy atomic.
- * This is the atomicity e.g. of IBM Power.
- * MO_ATOM_NONE: the operation has no atomicity requirements.
- *
- * Note the default (i.e. 0) value is single-copy atomic to the
- * size of the operation, if aligned. This retains the behaviour
- * from before this field was introduced.
- */
- MO_ATOM_SHIFT = 8,
- MO_ATOM_IFALIGN = 0 << MO_ATOM_SHIFT,
- MO_ATOM_IFALIGN_PAIR = 1 << MO_ATOM_SHIFT,
- MO_ATOM_WITHIN16 = 2 << MO_ATOM_SHIFT,
- MO_ATOM_WITHIN16_PAIR = 3 << MO_ATOM_SHIFT,
- MO_ATOM_SUBALIGN = 4 << MO_ATOM_SHIFT,
- MO_ATOM_NONE = 5 << MO_ATOM_SHIFT,
- MO_ATOM_MASK = 7 << MO_ATOM_SHIFT,
- /* Combinations of the above, for ease of use. */
- MO_UB = MO_8,
- MO_UW = MO_16,
- MO_UL = MO_32,
- MO_UQ = MO_64,
- MO_UO = MO_128,
- MO_SB = MO_SIGN | MO_8,
- MO_SW = MO_SIGN | MO_16,
- MO_SL = MO_SIGN | MO_32,
- MO_SQ = MO_SIGN | MO_64,
- MO_SO = MO_SIGN | MO_128,
- MO_LEUW = MO_LE | MO_UW,
- MO_LEUL = MO_LE | MO_UL,
- MO_LEUQ = MO_LE | MO_UQ,
- MO_LESW = MO_LE | MO_SW,
- MO_LESL = MO_LE | MO_SL,
- MO_LESQ = MO_LE | MO_SQ,
- MO_BEUW = MO_BE | MO_UW,
- MO_BEUL = MO_BE | MO_UL,
- MO_BEUQ = MO_BE | MO_UQ,
- MO_BESW = MO_BE | MO_SW,
- MO_BESL = MO_BE | MO_SL,
- MO_BESQ = MO_BE | MO_SQ,
- #ifdef COMPILING_PER_TARGET
- MO_TEUW = MO_TE | MO_UW,
- MO_TEUL = MO_TE | MO_UL,
- MO_TEUQ = MO_TE | MO_UQ,
- MO_TEUO = MO_TE | MO_UO,
- MO_TESW = MO_TE | MO_SW,
- MO_TESL = MO_TE | MO_SL,
- MO_TESQ = MO_TE | MO_SQ,
- #endif
- MO_SSIZE = MO_SIZE | MO_SIGN,
- } MemOp;
- /* MemOp to size in bytes. */
- static inline unsigned memop_size(MemOp op)
- {
- return 1 << (op & MO_SIZE);
- }
- /* Size in bytes to MemOp. */
- static inline MemOp size_memop(unsigned size)
- {
- #ifdef CONFIG_DEBUG_TCG
- /* Power of 2 up to 8. */
- assert((size & (size - 1)) == 0 && size >= 1 && size <= 8);
- #endif
- return (MemOp)ctz32(size);
- }
- /**
- * memop_alignment_bits:
- * @memop: MemOp value
- *
- * Extract the alignment size from the memop.
- */
- static inline unsigned memop_alignment_bits(MemOp memop)
- {
- unsigned a = memop & MO_AMASK;
- if (a == MO_UNALN) {
- /* No alignment required. */
- a = 0;
- } else if (a == MO_ALIGN) {
- /* A natural alignment requirement. */
- a = memop & MO_SIZE;
- } else {
- /* A specific alignment requirement. */
- a = a >> MO_ASHIFT;
- }
- return a;
- }
- /*
- * memop_atomicity_bits:
- * @memop: MemOp value
- *
- * Extract the atomicity size from the memop.
- */
- static inline unsigned memop_atomicity_bits(MemOp memop)
- {
- unsigned size = memop & MO_SIZE;
- switch (memop & MO_ATOM_MASK) {
- case MO_ATOM_NONE:
- size = MO_8;
- break;
- case MO_ATOM_IFALIGN_PAIR:
- case MO_ATOM_WITHIN16_PAIR:
- size = size ? size - 1 : 0;
- break;
- default:
- break;
- }
- return size;
- }
- #endif
|