(linenum→info "unix/slp.c:2238")

qemu/0.9.1/cpu-all.h

    1: /*
    2:  * defines common to all virtual CPUs
    3:  *
    4:  *  Copyright (c) 2003 Fabrice Bellard
    5:  *
    6:  * This library is free software; you can redistribute it and/or
    7:  * modify it under the terms of the GNU Lesser General Public
    8:  * License as published by the Free Software Foundation; either
    9:  * version 2 of the License, or (at your option) any later version.
   10:  *
   11:  * This library is distributed in the hope that it will be useful,
   12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:  * Lesser General Public License for more details.
   15:  *
   16:  * You should have received a copy of the GNU Lesser General Public
   17:  * License along with this library; if not, write to the Free Software
   18:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   19:  */
   20: #ifndef CPU_ALL_H
   21: #define CPU_ALL_H
   22: 
   23: #if defined(__arm__) || defined(__sparc__) || defined(__mips__)
   24: #define WORDS_ALIGNED
   25: #endif
   26: 
   27: /* some important defines:
   28:  *
   29:  * WORDS_ALIGNED : if defined, the host cpu can only make word aligned
   30:  * memory accesses.
   31:  *
   32:  * WORDS_BIGENDIAN : if defined, the host cpu is big endian and
   33:  * otherwise little endian.
   34:  *
   35:  * (TARGET_WORDS_ALIGNED : same for target cpu (not supported yet))
   36:  *
   37:  * TARGET_WORDS_BIGENDIAN : same for target cpu
   38:  */
   39: 
   40: #include "bswap.h"
   41: 
   42: #if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
   43: #define BSWAP_NEEDED
   44: #endif
   45: 
   46: #ifdef BSWAP_NEEDED
   47: 
   48: static inline uint16_t tswap16(uint16_t s)
   49: {
   50:     return bswap16(s);
   51: }
   52: 
   53: static inline uint32_t tswap32(uint32_t s)
   54: {
   55:     return bswap32(s);
   56: }
   57: 
   58: static inline uint64_t tswap64(uint64_t s)
   59: {
   60:     return bswap64(s);
   61: }
   62: 
   63: static inline void tswap16s(uint16_t *s)
   64: {
   65:     *s = bswap16(*s);
   66: }
   67: 
   68: static inline void tswap32s(uint32_t *s)
   69: {
   70:     *s = bswap32(*s);
   71: }
   72: 
   73: static inline void tswap64s(uint64_t *s)
   74: {
   75:     *s = bswap64(*s);
   76: }
   77: 
   78: #else
   79: 
   80: static inline uint16_t tswap16(uint16_t s)
   81: {
   82:     return s;
   83: }
   84: 
   85: static inline uint32_t tswap32(uint32_t s)
   86: {
   87:     return s;
   88: }
   89: 
   90: static inline uint64_t tswap64(uint64_t s)
   91: {
   92:     return s;
   93: }
   94: 
   95: static inline void tswap16s(uint16_t *s)
   96: {
   97: }
   98: 
   99: static inline void tswap32s(uint32_t *s)
  100: {
  101: }
  102: 
  103: static inline void tswap64s(uint64_t *s)
  104: {
  105: }
  106: 
  107: #endif
  108: 
  109: #if TARGET_LONG_SIZE == 4
  110: #define tswapl(s) tswap32(s)
  111: #define tswapls(s) tswap32s((uint32_t *)(s))
  112: #define bswaptls(s) bswap32s(s)
  113: #else
  114: #define tswapl(s) tswap64(s)
  115: #define tswapls(s) tswap64s((uint64_t *)(s))
  116: #define bswaptls(s) bswap64s(s)
  117: #endif
  118: 
  119: /* NOTE: arm FPA is horrible as double 32 bit words are stored in big
  120:    endian ! */
  121: typedef union {
  122:     float64 d;
  123: #if defined(WORDS_BIGENDIAN) \
  124:     || (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT))
  125:     struct {
  126:         uint32_t upper;
  127:         uint32_t lower;
  128:     } l;
  129: #else
  130:     struct {
  131:         uint32_t lower;
  132:         uint32_t upper;
  133:     } l;
  134: #endif
  135:     uint64_t ll;
  136: } CPU_DoubleU;
  137: 
  138: #ifdef TARGET_SPARC
  139: typedef union {
  140:     float128 q;
  141: #if defined(WORDS_BIGENDIAN) \
  142:     || (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT))
  143:     struct {
  144:         uint32_t upmost;
  145:         uint32_t upper;
  146:         uint32_t lower;
  147:         uint32_t lowest;
  148:     } l;
  149:     struct {
  150:         uint64_t upper;
  151:         uint64_t lower;
  152:     } ll;
  153: #else
  154:     struct {
  155:         uint32_t lowest;
  156:         uint32_t lower;
  157:         uint32_t upper;
  158:         uint32_t upmost;
  159:     } l;
  160:     struct {
  161:         uint64_t lower;
  162:         uint64_t upper;
  163:     } ll;
  164: #endif
  165: } CPU_QuadU;
  166: #endif
  167: 
  168: /* CPU memory access without any memory or io remapping */
  169: 
  170: /*
  171:  * the generic syntax for the memory accesses is:
  172:  *
  173:  * load: ld{type}{sign}{size}{endian}_{access_type}(ptr)
  174:  *
  175:  * store: st{type}{size}{endian}_{access_type}(ptr, val)
  176:  *
  177:  * type is:
  178:  * (empty): integer access
  179:  *   f    : float access
  180:  *
  181:  * sign is:
  182:  * (empty): for floats or 32 bit size
  183:  *   u    : unsigned
  184:  *   s    : signed
  185:  *
  186:  * size is:
  187:  *   b: 8 bits
  188:  *   w: 16 bits
  189:  *   l: 32 bits
  190:  *   q: 64 bits
  191:  *
  192:  * endian is:
  193:  * (empty): target cpu endianness or 8 bit access
  194:  *   r    : reversed target cpu endianness (not implemented yet)
  195:  *   be   : big endian (not implemented yet)
  196:  *   le   : little endian (not implemented yet)
  197:  *
  198:  * access_type is:
  199:  *   raw    : host memory access
  200:  *   user   : user mode access using soft MMU
  201:  *   kernel : kernel mode access using soft MMU
  202:  */
  203: static inline int ldub_p(void *ptr)
  204: {
  205:     return *(uint8_t *)ptr;
  206: }
  207: 
  208: static inline int ldsb_p(void *ptr)
  209: {
  210:     return *(int8_t *)ptr;
  211: }
  212: 
  213: static inline void stb_p(void *ptr, int v)
  214: {
  215:     *(uint8_t *)ptr = v;
  216: }
  217: 
  218: /* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
  219:    kernel handles unaligned load/stores may give better results, but
  220:    it is a system wide setting : bad */
  221: #if defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
  222: 
  223: /* conservative code for little endian unaligned accesses */
  224: static inline int lduw_le_p(void *ptr)
  225: {
  226: #ifdef __powerpc__
  227:     int val;
  228:     __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
  229:     return val;
  230: #else
  231:     uint8_t *p = ptr;
  232:     return p[0] | (p[1] << 8);
  233: #endif
  234: }
  235: 
  236: static inline int ldsw_le_p(void *ptr)
  237: {
  238: #ifdef __powerpc__
  239:     int val;
  240:     __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
  241:     return (int16_t)val;
  242: #else
  243:     uint8_t *p = ptr;
  244:     return (int16_t)(p[0] | (p[1] << 8));
  245: #endif
  246: }
  247: 
  248: static inline int ldl_le_p(void *ptr)
  249: {
  250: #ifdef __powerpc__
  251:     int val;
  252:     __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
  253:     return val;
  254: #else
  255:     uint8_t *p = ptr;
  256:     return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
  257: #endif
  258: }
  259: 
  260: static inline uint64_t ldq_le_p(void *ptr)
  261: {
  262:     uint8_t *p = ptr;
  263:     uint32_t v1, v2;
  264:     v1 = ldl_le_p(p);
  265:     v2 = ldl_le_p(p + 4);
  266:     return v1 | ((uint64_t)v2 << 32);
  267: }
  268: 
  269: static inline void stw_le_p(void *ptr, int v)
  270: {
  271: #ifdef __powerpc__
  272:     __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
  273: #else
  274:     uint8_t *p = ptr;
  275:     p[0] = v;
  276:     p[1] = v >> 8;
  277: #endif
  278: }
  279: 
  280: static inline void stl_le_p(void *ptr, int v)
  281: {
  282: #ifdef __powerpc__
  283:     __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
  284: #else
  285:     uint8_t *p = ptr;
  286:     p[0] = v;
  287:     p[1] = v >> 8;
  288:     p[2] = v >> 16;
  289:     p[3] = v >> 24;
  290: #endif
  291: }
  292: 
  293: static inline void stq_le_p(void *ptr, uint64_t v)
  294: {
  295:     uint8_t *p = ptr;
  296:     stl_le_p(p, (uint32_t)v);
  297:     stl_le_p(p + 4, v >> 32);
  298: }
  299: 
  300: /* float access */
  301: 
  302: static inline float32 ldfl_le_p(void *ptr)
  303: {
  304:     union {
  305:         float32 f;
  306:         uint32_t i;
  307:     } u;
  308:     u.i = ldl_le_p(ptr);
  309:     return u.f;
  310: }
  311: 
  312: static inline void stfl_le_p(void *ptr, float32 v)
  313: {
  314:     union {
  315:         float32 f;
  316:         uint32_t i;
  317:     } u;
  318:     u.f = v;
  319:     stl_le_p(ptr, u.i);
  320: }
  321: 
  322: static inline float64 ldfq_le_p(void *ptr)
  323: {
  324:     CPU_DoubleU u;
  325:     u.l.lower = ldl_le_p(ptr);
  326:     u.l.upper = ldl_le_p(ptr + 4);
  327:     return u.d;
  328: }
  329: 
  330: static inline void stfq_le_p(void *ptr, float64 v)
  331: {
  332:     CPU_DoubleU u;
  333:     u.d = v;
  334:     stl_le_p(ptr, u.l.lower);
  335:     stl_le_p(ptr + 4, u.l.upper);
  336: }
  337: 
  338: #else
  339: 
  340: static inline int lduw_le_p(void *ptr)
  341: {
  342:     return *(uint16_t *)ptr;
  343: }
  344: 
  345: static inline int ldsw_le_p(void *ptr)
  346: {
  347:     return *(int16_t *)ptr;
  348: }
  349: 
  350: static inline int ldl_le_p(void *ptr)
  351: {
  352:     return *(uint32_t *)ptr;
  353: }
  354: 
  355: static inline uint64_t ldq_le_p(void *ptr)
  356: {
  357:     return *(uint64_t *)ptr;
  358: }
  359: 
  360: static inline void stw_le_p(void *ptr, int v)
  361: {
  362:     *(uint16_t *)ptr = v;
  363: }
  364: 
  365: static inline void stl_le_p(void *ptr, int v)
  366: {
  367:     *(uint32_t *)ptr = v;
  368: }
  369: 
  370: static inline void stq_le_p(void *ptr, uint64_t v)
  371: {
  372:     *(uint64_t *)ptr = v;
  373: }
  374: 
  375: /* float access */
  376: 
  377: static inline float32 ldfl_le_p(void *ptr)
  378: {
  379:     return *(float32 *)ptr;
  380: }
  381: 
  382: static inline float64 ldfq_le_p(void *ptr)
  383: {
  384:     return *(float64 *)ptr;
  385: }
  386: 
  387: static inline void stfl_le_p(void *ptr, float32 v)
  388: {
  389:     *(float32 *)ptr = v;
  390: }
  391: 
  392: static inline void stfq_le_p(void *ptr, float64 v)
  393: {
  394:     *(float64 *)ptr = v;
  395: }
  396: #endif
  397: 
  398: #if !defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
  399: 
  400: static inline int lduw_be_p(void *ptr)
  401: {
  402: #if defined(__i386__)
  403:     int val;
  404:     asm volatile ("movzwl %1, %0\n"
  405:                   "xchgb %b0, %h0\n"
  406:                   : "=q" (val)
  407:                   : "m" (*(uint16_t *)ptr));
  408:     return val;
  409: #else
  410:     uint8_t *b = (uint8_t *) ptr;
  411:     return ((b[0] << 8) | b[1]);
  412: #endif
  413: }
  414: 
  415: static inline int ldsw_be_p(void *ptr)
  416: {
  417: #if defined(__i386__)
  418:     int val;
  419:     asm volatile ("movzwl %1, %0\n"
  420:                   "xchgb %b0, %h0\n"
  421:                   : "=q" (val)
  422:                   : "m" (*(uint16_t *)ptr));
  423:     return (int16_t)val;
  424: #else
  425:     uint8_t *b = (uint8_t *) ptr;
  426:     return (int16_t)((b[0] << 8) | b[1]);
  427: #endif
  428: }
  429: 
  430: static inline int ldl_be_p(void *ptr)
  431: {
  432: #if defined(__i386__) || defined(__x86_64__)
  433:     int val;
  434:     asm volatile ("movl %1, %0\n"
  435:                   "bswap %0\n"
  436:                   : "=r" (val)
  437:                   : "m" (*(uint32_t *)ptr));
  438:     return val;
  439: #else
  440:     uint8_t *b = (uint8_t *) ptr;
  441:     return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
  442: #endif
  443: }
  444: 
  445: static inline uint64_t ldq_be_p(void *ptr)
  446: {
  447:     uint32_t a,b;
  448:     a = ldl_be_p(ptr);
  449:     b = ldl_be_p(ptr+4);
  450:     return (((uint64_t)a<<32)|b);
  451: }
  452: 
  453: static inline void stw_be_p(void *ptr, int v)
  454: {
  455: #if defined(__i386__)
  456:     asm volatile ("xchgb %b0, %h0\n"
  457:                   "movw %w0, %1\n"
  458:                   : "=q" (v)
  459:                   : "m" (*(uint16_t *)ptr), "0" (v));
  460: #else
  461:     uint8_t *d = (uint8_t *) ptr;
  462:     d[0] = v >> 8;
  463:     d[1] = v;
  464: #endif
  465: }
  466: 
  467: static inline void stl_be_p(void *ptr, int v)
  468: {
  469: #if defined(__i386__) || defined(__x86_64__)
  470:     asm volatile ("bswap %0\n"
  471:                   "movl %0, %1\n"
  472:                   : "=r" (v)
  473:                   : "m" (*(uint32_t *)ptr), "0" (v));
  474: #else
  475:     uint8_t *d = (uint8_t *) ptr;
  476:     d[0] = v >> 24;
  477:     d[1] = v >> 16;
  478:     d[2] = v >> 8;
  479:     d[3] = v;
  480: #endif
  481: }
  482: 
  483: static inline void stq_be_p(void *ptr, uint64_t v)
  484: {
  485:     stl_be_p(ptr, v >> 32);
  486:     stl_be_p(ptr + 4, v);
  487: }
  488: 
  489: /* float access */
  490: 
  491: static inline float32 ldfl_be_p(void *ptr)
  492: {
  493:     union {
  494:         float32 f;
  495:         uint32_t i;
  496:     } u;
  497:     u.i = ldl_be_p(ptr);
  498:     return u.f;
  499: }
  500: 
  501: static inline void stfl_be_p(void *ptr, float32 v)
  502: {
  503:     union {
  504:         float32 f;
  505:         uint32_t i;
  506:     } u;
  507:     u.f = v;
  508:     stl_be_p(ptr, u.i);
  509: }
  510: 
  511: static inline float64 ldfq_be_p(void *ptr)
  512: {
  513:     CPU_DoubleU u;
  514:     u.l.upper = ldl_be_p(ptr);
  515:     u.l.lower = ldl_be_p(ptr + 4);
  516:     return u.d;
  517: }
  518: 
  519: static inline void stfq_be_p(void *ptr, float64 v)
  520: {
  521:     CPU_DoubleU u;
  522:     u.d = v;
  523:     stl_be_p(ptr, u.l.upper);
  524:     stl_be_p(ptr + 4, u.l.lower);
  525: }
  526: 
  527: #else
  528: 
  529: static inline int lduw_be_p(void *ptr)
  530: {
  531:     return *(uint16_t *)ptr;
  532: }
  533: 
  534: static inline int ldsw_be_p(void *ptr)
  535: {
  536:     return *(int16_t *)ptr;
  537: }
  538: 
  539: static inline int ldl_be_p(void *ptr)
  540: {
  541:     return *(uint32_t *)ptr;
  542: }
  543: 
  544: static inline uint64_t ldq_be_p(void *ptr)
  545: {
  546:     return *(uint64_t *)ptr;
  547: }
  548: 
  549: static inline void stw_be_p(void *ptr, int v)
  550: {
  551:     *(uint16_t *)ptr = v;
  552: }
  553: 
  554: static inline void stl_be_p(void *ptr, int v)
  555: {
  556:     *(uint32_t *)ptr = v;
  557: }
  558: 
  559: static inline void stq_be_p(void *ptr, uint64_t v)
  560: {
  561:     *(uint64_t *)ptr = v;
  562: }
  563: 
  564: /* float access */
  565: 
  566: static inline float32 ldfl_be_p(void *ptr)
  567: {
  568:     return *(float32 *)ptr;
  569: }
  570: 
  571: static inline float64 ldfq_be_p(void *ptr)
  572: {
  573:     return *(float64 *)ptr;
  574: }
  575: 
  576: static inline void stfl_be_p(void *ptr, float32 v)
  577: {
  578:     *(float32 *)ptr = v;
  579: }
  580: 
  581: static inline void stfq_be_p(void *ptr, float64 v)
  582: {
  583:     *(float64 *)ptr = v;
  584: }
  585: 
  586: #endif
  587: 
  588: /* target CPU memory access functions */
  589: #if defined(TARGET_WORDS_BIGENDIAN)
  590: #define lduw_p(p) lduw_be_p(p)
  591: #define ldsw_p(p) ldsw_be_p(p)
  592: #define ldl_p(p) ldl_be_p(p)
  593: #define ldq_p(p) ldq_be_p(p)
  594: #define ldfl_p(p) ldfl_be_p(p)
  595: #define ldfq_p(p) ldfq_be_p(p)
  596: #define stw_p(p, v) stw_be_p(p, v)
  597: #define stl_p(p, v) stl_be_p(p, v)
  598: #define stq_p(p, v) stq_be_p(p, v)
  599: #define stfl_p(p, v) stfl_be_p(p, v)
  600: #define stfq_p(p, v) stfq_be_p(p, v)
  601: #else
  602: #define lduw_p(p) lduw_le_p(p)
  603: #define ldsw_p(p) ldsw_le_p(p)
  604: #define ldl_p(p) ldl_le_p(p)
  605: #define ldq_p(p) ldq_le_p(p)
  606: #define ldfl_p(p) ldfl_le_p(p)
  607: #define ldfq_p(p) ldfq_le_p(p)
  608: #define stw_p(p, v) stw_le_p(