qemu学习(二)————qemu中对处理器大小端的设置
来源:互联网 发布:淘宝左侧排名收费 编辑:程序博客网 时间:2024/06/07 22:09
《一日二十四挨踢www.1024it.net》站文章在未特殊说明下默认为原创性文章。
在未有正式书面授权情况下,请勿转载。谢谢配合
/****************************************************************************** * Copyright (c) 2011 IBM Corporation * All rights reserved. * This program and the accompanying materials * are made available under the terms of the BSD License * which accompanies this distribution, and is available at * http://www.opensource.org/licenses/bsd-license.php * * Contributors: * IBM Corporation - initial implementation *****************************************************************************//* * Common byteorder (endianess) macros */#ifndef BYTEORDER_H#define BYTEORDER_Hstatic inline uint16_tbswap_16 (uint16_t x){ return ((x&0xff00) >> 8) | ((x&0xff) << 8);}static inline uint32_tbswap_32 (uint32_t x){ return bswap_16(x >> 16) | (bswap_16(x) << 16);}static inline uint64_tbswap_64 (uint64_t x){ return (uint64_t) bswap_32(x >> 32) | (uint64_t) bswap_32(x) << 32;}/* gcc defines __BIG_ENDIAN__ on big endian targets */#ifdef __BIG_ENDIAN__#define cpu_to_be16(x) (x)#define cpu_to_be32(x) (x)#define cpu_to_be64(x) (x)#define be16_to_cpu(x) (x)#define be32_to_cpu(x) (x)#define be64_to_cpu(x) (x)#define le16_to_cpu(x) bswap_16(x)#define le32_to_cpu(x) bswap_32(x)#define le64_to_cpu(x) bswap_64(x)#define cpu_to_le16(x) bswap_16(x)#define cpu_to_le32(x) bswap_32(x)#define cpu_to_le64(x) bswap_64(x)#else#define cpu_to_be16(x) bswap_16(x)#define cpu_to_be32(x) bswap_32(x)#define cpu_to_be64(x) bswap_64(x)#define be16_to_cpu(x) bswap_16(x)#define be32_to_cpu(x) bswap_32(x)#define be64_to_cpu(x) bswap_64(x)#define le16_to_cpu(x) (x)#define le32_to_cpu(x) (x)#define le64_to_cpu(x) (x)#define cpu_to_le16(x) (x)#define cpu_to_le32(x) (x)#define cpu_to_le64(x) (x)#endif /* __BIG_ENDIAN__ */#endif /* BYTEORDER_H */
上面的code存在于./roms/SLOF/include/byteorder.h中,用来控制字节顺序。
下面的三个函数,通过移位用算实现了16、32、64位整数的高低两部分的转换。(这里有个疑问,大小端是按照字节来布局的,还是按照整型数位数的一半????)
static inline uint16_tbswap_16 (uint16_t x){ return ((x&0xff00) >> 8) | ((x&0xff) << 8);}static inline uint32_tbswap_32 (uint32_t x){ return bswap_16(x >> 16) | (bswap_16(x) << 16);}static inline uint64_tbswap_64 (uint64_t x){ return (uint64_t) bswap_32(x >> 32) | (uint64_t) bswap_32(x) << 32;}
通过宏#ifdef __BIG_ENDIAN__来选择大端和小端。
********************************************************************************************************************************************************************
********************************************************************************************************************************************************************
前面提到了./roms/SLOF/include/byteorder.h里的字节序列,也提出了疑问。下面加入./include/qemu/bswap.h处关于大小端的定义(注意宏定义的if 和 else):#ifndef BSWAP_H#define BSWAP_H#include "config-host.h"#include <inttypes.h>#include <limits.h>#include "fpu/softfloat.h"#ifdef CONFIG_MACHINE_BSWAP_H# include <sys/endian.h># include <sys/types.h># include <machine/bswap.h>#elif defined(CONFIG_BYTESWAP_H)# include <byteswap.h>static inline uint16_t bswap16(uint16_t x){ return bswap_16(x);}static inline uint32_t bswap32(uint32_t x){ return bswap_32(x);}static inline uint64_t bswap64(uint64_t x){ return bswap_64(x);}# elsestatic inline uint16_t bswap16(uint16_t x){ return (((x & 0x00ff) << 8) | ((x & 0xff00) >> 8));}static inline uint32_t bswap32(uint32_t x){ return (((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) << 8) | ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24));}static inline uint64_t bswap64(uint64_t x){ return (((x & 0x00000000000000ffULL) << 56) | ((x & 0x000000000000ff00ULL) << 40) | ((x & 0x0000000000ff0000ULL) << 24) | ((x & 0x00000000ff000000ULL) << 8) | ((x & 0x000000ff00000000ULL) >> 8) | ((x & 0x0000ff0000000000ULL) >> 24) | ((x & 0x00ff000000000000ULL) >> 40) | ((x & 0xff00000000000000ULL) >> 56));}#endif /* ! CONFIG_MACHINE_BSWAP_H */static inline void bswap16s(uint16_t *s){ *s = bswap16(*s);}static inline void bswap32s(uint32_t *s){ *s = bswap32(*s);}static inline void bswap64s(uint64_t *s){ *s = bswap64(*s);}#if defined(HOST_WORDS_BIGENDIAN)#define be_bswap(v, size) (v)#define le_bswap(v, size) glue(bswap, size)(v)#define be_bswaps(v, size)#define le_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)#else#define le_bswap(v, size) (v)#define be_bswap(v, size) glue(bswap, size)(v)#define le_bswaps(v, size)#define be_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)#endif#define CPU_CONVERT(endian, size, type)\static inline type endian ## size ## _to_cpu(type v)\{\ return glue(endian, _bswap)(v, size);\}\\static inline type cpu_to_ ## endian ## size(type v)\{\ return glue(endian, _bswap)(v, size);\}\\static inline void endian ## size ## _to_cpus(type *p)\{\ glue(endian, _bswaps)(p, size);\}\\static inline void cpu_to_ ## endian ## size ## s(type *p)\{\ glue(endian, _bswaps)(p, size);\}\\static inline type endian ## size ## _to_cpup(const type *p)\{\ return glue(glue(endian, size), _to_cpu)(*p);\}\\static inline void cpu_to_ ## endian ## size ## w(type *p, type v)\{\ *p = glue(glue(cpu_to_, endian), size)(v);\}CPU_CONVERT(be, 16, uint16_t)CPU_CONVERT(be, 32, uint32_t)CPU_CONVERT(be, 64, uint64_t)CPU_CONVERT(le, 16, uint16_t)CPU_CONVERT(le, 32, uint32_t)CPU_CONVERT(le, 64, uint64_t)/* len must be one of 1, 2, 4 */static inline uint32_t qemu_bswap_len(uint32_t value, int len){ return bswap32(value) >> (32 - 8 * len);}/* Unions for reinterpreting between floats and integers. */typedef union { float32 f; uint32_t l;} CPU_FloatU;typedef union { float64 d;#if defined(HOST_WORDS_BIGENDIAN) struct { uint32_t upper; uint32_t lower; } l;#else struct { uint32_t lower; uint32_t upper; } l;#endif uint64_t ll;} CPU_DoubleU;typedef union { floatx80 d; struct { uint64_t lower; uint16_t upper; } l;} CPU_LDoubleU;typedef union { float128 q;#if defined(HOST_WORDS_BIGENDIAN) struct { uint32_t upmost; uint32_t upper; uint32_t lower; uint32_t lowest; } l; struct { uint64_t upper; uint64_t lower; } ll;#else struct { uint32_t lowest; uint32_t lower; uint32_t upper; uint32_t upmost; } l; struct { uint64_t lower; uint64_t upper; } ll;#endif} CPU_QuadU;/* unaligned/endian-independent pointer access *//* * the generic syntax is: * * load: ld{type}{sign}{size}{endian}_p(ptr) * * store: st{type}{size}{endian}_p(ptr, val) * * Note there are small differences with the softmmu access API! * * type is: * (empty): integer access * f : float access * * sign is: * (empty): for floats or 32 bit size * u : unsigned * s : signed * * size is: * b: 8 bits * w: 16 bits * l: 32 bits * q: 64 bits * * endian is: * (empty): host endian * be : big endian * le : little endian */static inline int ldub_p(const void *ptr){ return *(uint8_t *)ptr;}static inline int ldsb_p(const void *ptr){ return *(int8_t *)ptr;}static inline void stb_p(void *ptr, int v){ *(uint8_t *)ptr = v;}/* Any compiler worth its salt will turn these memcpy into native unaligned operations. Thus we don't need to play games with packed attributes, or inline byte-by-byte stores. */static inline int lduw_p(const void *ptr){ uint16_t r; memcpy(&r, ptr, sizeof(r)); return r;}static inline int ldsw_p(const void *ptr){ int16_t r; memcpy(&r, ptr, sizeof(r)); return r;}static inline void stw_p(void *ptr, uint16_t v){ memcpy(ptr, &v, sizeof(v));}static inline int ldl_p(const void *ptr){ int32_t r; memcpy(&r, ptr, sizeof(r)); return r;}static inline void stl_p(void *ptr, uint32_t v){ memcpy(ptr, &v, sizeof(v));}static inline uint64_t ldq_p(const void *ptr){ uint64_t r; memcpy(&r, ptr, sizeof(r)); return r;}static inline void stq_p(void *ptr, uint64_t v){ memcpy(ptr, &v, sizeof(v));}static inline int lduw_le_p(const void *ptr){ return (uint16_t)le_bswap(lduw_p(ptr), 16);}static inline int ldsw_le_p(const void *ptr){ return (int16_t)le_bswap(lduw_p(ptr), 16);}static inline int ldl_le_p(const void *ptr){ return le_bswap(ldl_p(ptr), 32);}static inline uint64_t ldq_le_p(const void *ptr){ return le_bswap(ldq_p(ptr), 64);}static inline void stw_le_p(void *ptr, int v){ stw_p(ptr, le_bswap(v, 16));}static inline void stl_le_p(void *ptr, int v){ stl_p(ptr, le_bswap(v, 32));}static inline void stq_le_p(void *ptr, uint64_t v){ stq_p(ptr, le_bswap(v, 64));}/* float access */static inline float32 ldfl_le_p(const void *ptr){ CPU_FloatU u; u.l = ldl_le_p(ptr); return u.f;}static inline void stfl_le_p(void *ptr, float32 v){ CPU_FloatU u; u.f = v; stl_le_p(ptr, u.l);}static inline float64 ldfq_le_p(const void *ptr){ CPU_DoubleU u; u.ll = ldq_le_p(ptr); return u.d;}static inline void stfq_le_p(void *ptr, float64 v){ CPU_DoubleU u; u.d = v; stq_le_p(ptr, u.ll);}static inline int lduw_be_p(const void *ptr){ return (uint16_t)be_bswap(lduw_p(ptr), 16);}static inline int ldsw_be_p(const void *ptr){ return (int16_t)be_bswap(lduw_p(ptr), 16);}static inline int ldl_be_p(const void *ptr){ return be_bswap(ldl_p(ptr), 32);}static inline uint64_t ldq_be_p(const void *ptr){ return be_bswap(ldq_p(ptr), 64);}static inline void stw_be_p(void *ptr, int v){ stw_p(ptr, be_bswap(v, 16));}static inline void stl_be_p(void *ptr, int v){ stl_p(ptr, be_bswap(v, 32));}static inline void stq_be_p(void *ptr, uint64_t v){ stq_p(ptr, be_bswap(v, 64));}/* float access */static inline float32 ldfl_be_p(const void *ptr){ CPU_FloatU u; u.l = ldl_be_p(ptr); return u.f;}static inline void stfl_be_p(void *ptr, float32 v){ CPU_FloatU u; u.f = v; stl_be_p(ptr, u.l);}static inline float64 ldfq_be_p(const void *ptr){ CPU_DoubleU u; u.ll = ldq_be_p(ptr); return u.d;}static inline void stfq_be_p(void *ptr, float64 v){ CPU_DoubleU u; u.d = v; stq_be_p(ptr, u.ll);}/* Legacy unaligned versions. Note that we never had a complete set. */static inline void cpu_to_le16wu(uint16_t *p, uint16_t v){ stw_le_p(p, v);}static inline void cpu_to_le32wu(uint32_t *p, uint32_t v){ stl_le_p(p, v);}static inline uint16_t le16_to_cpupu(const uint16_t *p){ return lduw_le_p(p);}static inline uint32_t le32_to_cpupu(const uint32_t *p){ return ldl_le_p(p);}static inline uint32_t be32_to_cpupu(const uint32_t *p){ return ldl_be_p(p);}static inline void cpu_to_be16wu(uint16_t *p, uint16_t v){ stw_be_p(p, v);}static inline void cpu_to_be32wu(uint32_t *p, uint32_t v){ stl_be_p(p, v);}static inline void cpu_to_be64wu(uint64_t *p, uint64_t v){ stq_be_p(p, v);}static inline void cpu_to_32wu(uint32_t *p, uint32_t v){ stl_p(p, v);}static inline unsigned long leul_to_cpu(unsigned long v){ /* In order to break an include loop between here and qemu-common.h, don't rely on HOST_LONG_BITS. */#if ULONG_MAX == UINT32_MAX return le_bswap(v, 32);#elif ULONG_MAX == UINT64_MAX return le_bswap(v, 64);#else# error Unknown sizeof long#endif}#undef le_bswap#undef be_bswap#undef le_bswaps#undef be_bswaps#endif /* BSWAP_H */
- qemu学习(二)————qemu中对处理器大小端的设置
- qemu学习(三)————qemu中反汇编操作解析
- qemu 学习(一)————qemu整体流程解读
- 关于qemu的二三事(1)————qemu的特殊参数之monitor
- 关于qemu的二三事(2)————qemu使用过程中的小tips
- 关于qemu的二三事(3)————如何给qemu打patch
- 关于qemu的二三事(5)————qemu源码分析之参数解析
- 关于qemu的二三事(6)————qemu源码分析之vcpu
- OpenStack学习:qemu(二)
- Android模拟器——QEMU
- Android模拟器——QEMU
- Android模拟器——QEMU
- 关于qemu的二三事(4)————qemu源码的下载与编译,以及fdt
- 内核虚拟化KVM/QEMU——guest os,qemu,kvm的运行流程
- 对KVM、qemu、qemu-kvm的理解
- 9.2 libvirt中对Qemu的控制
- KVM&QEMU学习笔记(二)
- QEMU 简介(二)
- Ember.js 概念详解--路由器
- Uglifyjs入门
- SQL Server 中 RAISERROR 的用法
- 2013年4月1日
- Hash的JAVA
- qemu学习(二)————qemu中对处理器大小端的设置
- Planning for Multiple Touchscreen Sizes 规划多个触摸屏尺寸
- 2013年4月2日
- 计算机科学中最重要的32个算法
- shell脚本的一些用法总汇
- 2013年4月4日
- 使用r.js压缩整个项目的JS
- C不常用的语法
- Android 一篇比较好的关于ScaleType的说明的文章