Annotation of tme/libtme/memory-auto.sh, revision 1.1

1.1     ! root        1: #! /bin/sh
        !             2: 
        !             3: # $Id: memory-auto.sh,v 1.1 2006/09/30 12:43:37 fredette Exp $
        !             4: 
        !             5: # libtme/memory-auto.sh - automatically generates C code for
        !             6: # memory support:
        !             7: 
        !             8: #
        !             9: # Copyright (c) 2005, 2006 Matt Fredette
        !            10: # All rights reserved.
        !            11: #
        !            12: # Redistribution and use in source and binary forms, with or without
        !            13: # modification, are permitted provided that the following conditions
        !            14: # are met:
        !            15: # 1. Redistributions of source code must retain the above copyright
        !            16: #    notice, this list of conditions and the following disclaimer.
        !            17: # 2. Redistributions in binary form must reproduce the above copyright
        !            18: #    notice, this list of conditions and the following disclaimer in the
        !            19: #    documentation and/or other materials provided with the distribution.
        !            20: # 3. All advertising materials mentioning features or use of this software
        !            21: #    must display the following acknowledgement:
        !            22: #      This product includes software developed by Matt Fredette.
        !            23: # 4. The name of the author may not be used to endorse or promote products
        !            24: #    derived from this software without specific prior written permission.
        !            25: #
        !            26: # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            27: # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            28: # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            29: # DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
        !            30: # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            31: # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            32: # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            33: # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            34: # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
        !            35: # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            36: # POSSIBILITY OF SUCH DAMAGE.
        !            37: #
        !            38: 
        !            39: header=false
        !            40: 
        !            41: for option
        !            42: do
        !            43:     case $option in
        !            44:     --header) header=true ;;
        !            45:     esac
        !            46: done
        !            47: 
        !            48: PROG=`basename $0`
        !            49: cat <<EOF
        !            50: /* automatically generated by $PROG, do not edit! */
        !            51: 
        !            52: /*
        !            53:  * Copyright (c) 2005, 2006 Matt Fredette
        !            54:  * All rights reserved.
        !            55:  *
        !            56:  * Redistribution and use in source and binary forms, with or without
        !            57:  * modification, are permitted provided that the following conditions
        !            58:  * are met:
        !            59:  * 1. Redistributions of source code must retain the above copyright
        !            60:  *    notice, this list of conditions and the following disclaimer.
        !            61:  * 2. Redistributions in binary form must reproduce the above copyright
        !            62:  *    notice, this list of conditions and the following disclaimer in the
        !            63:  *    documentation and/or other materials provided with the distribution.
        !            64:  * 3. All advertising materials mentioning features or use of this software
        !            65:  *    must display the following acknowledgement:
        !            66:  *      This product includes software developed by Matt Fredette.
        !            67:  * 4. The name of the author may not be used to endorse or promote products
        !            68:  *    derived from this software without specific prior written permission.
        !            69:  *
        !            70:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            71:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            72:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            73:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
        !            74:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            75:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            76:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            77:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            78:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
        !            79:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            80:  * POSSIBILITY OF SUCH DAMAGE.
        !            81:  */
        !            82: EOF
        !            83: 
        !            84: if $header; then :; else
        !            85:     cat <<EOF
        !            86: 
        !            87: /* includes: */
        !            88: #include <tme/memory.h>
        !            89: 
        !            90: EOF
        !            91: fi
        !            92: cat <<EOF
        !            93: 
        !            94: _TME_RCSID("\$Id: memory-auto.sh,v 1.1 2006/09/30 12:43:37 fredette Exp $");
        !            95: EOF
        !            96: if $header; then
        !            97:     cat <<EOF
        !            98: 
        !            99: /* macros: */
        !           100: 
        !           101: /* the plain partial read internal macro: */
        !           102: #define _tme_memory_read(type_whole, type_part, mem, offset)           \\
        !           103:   (((type_whole)                                                       \\
        !           104:     *((_tme_const type_part *)                                         \\
        !           105:       (_tme_cast_pointer_const(tme_uint8_t *, type_whole *, mem)       \\
        !           106:        + (offset))))                                                   \\
        !           107:    << (8 * (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG                                \\
        !           108:            ? (sizeof(type_whole)                                       \\
        !           109:               - ((offset) + sizeof(type_part)))                        \\
        !           110:            : (offset))))
        !           111: 
        !           112: /* the plain partial write internal macro: */
        !           113: #define _tme_memory_write(type_whole, type_part, mem, offset, x)       \\
        !           114:   do {                                                                 \\
        !           115:     *((type_part *)                                                    \\
        !           116:       (_tme_cast_pointer(tme_uint8_t *, type_whole *, mem)             \\
        !           117:        + (offset)))                                                    \\
        !           118:       = (((type_whole) (x))                                            \\
        !           119:         >> (8 * (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG                   \\
        !           120:                  ? (sizeof(type_whole)                                 \\
        !           121:                     - ((offset) + sizeof(type_part)))                  \\
        !           122:                  : (offset))));                                        \\
        !           123:   } while (/* CONSTCOND */ 0)
        !           124: 
        !           125: /* this tests bits in a memory address: */
        !           126: #define _tme_memory_address_test(mem, bits, align_min)                 \\
        !           127:   (((bits) & ~((align_min - 1))) & ((unsigned long) (mem)))
        !           128: 
        !           129: /* this returns a mask of all-bits-one in given type: */
        !           130: #define _tme_memory_type_mask(type, shift)                             \\
        !           131:   ((type) ((((type) 0) - ((type) 1)) shift))
        !           132: 
        !           133: EOF
        !           134: fi
        !           135: 
        !           136: # the different sizes we handle, and the smallest size that we have to
        !           137: # wrap in an ifdef:
        !           138: #
        !           139: sizes='8 16 32 64'
        !           140: size_ifdef=64
        !           141: 
        !           142: # the largest possible host boundary that we will consider:
        !           143: #
        !           144: host_boundary_largest=64
        !           145: 
        !           146: # permute for the different sizes:
        !           147: #
        !           148: for size in ${sizes}; do
        !           149: 
        !           150:     # we don't need bus eight-bit read and write slow functions: 
        !           151:     #
        !           152:     if test ${size} = 8; then continue; fi
        !           153: 
        !           154:     if test `expr ${size} \>= ${size_ifdef}` = 1; then
        !           155:        echo ""
        !           156:        echo "#ifdef TME_HAVE_INT${size}_T"
        !           157:     fi
        !           158: 
        !           159:     # emit the bus read and write slow functions:
        !           160:     #
        !           161:     for op in read write; do
        !           162: 
        !           163:        # dispatch on the operation:
        !           164:        #
        !           165:        if test ${op} = read; then
        !           166:            op_return_type="tme_uint${size}_t"
        !           167:            op_cap=READ
        !           168:            op_const="_tme_const "
        !           169:            op_proto_operand=
        !           170:            op_operand=
        !           171:        else
        !           172:            op_return_type=void
        !           173:            op_cap=WRITE
        !           174:            op_const=
        !           175:            op_proto_operand=", tme_uint${size}_t"
        !           176:            op_operand="${op_proto_operand} x"
        !           177:        fi
        !           178: 
        !           179:        # if we're making the header, just emit a prototype:
        !           180:        #
        !           181:        if $header; then
        !           182:            echo ""
        !           183:            echo "/* the bus ${size}-bit ${op} slow function: */"
        !           184:            echo "${op_return_type} tme_memory_bus_${op}${size} _TME_P((${op_const}tme_shared tme_uint${size}_t *${op_proto_operand}, tme_rwlock_t *, unsigned int, unsigned int));"
        !           185:            continue
        !           186:        fi
        !           187: 
        !           188:        echo ""
        !           189:        echo "/* undefine the macro version of tme_memory_bus_${op}${size}: */"
        !           190:        echo "#undef tme_memory_bus_${op}${size}"
        !           191:        echo ""
        !           192:        echo "/* the bus ${size}-bit ${op} slow function: */"
        !           193:        echo ${op_return_type}
        !           194:        echo "tme_memory_bus_${op}${size}(${op_const}tme_shared tme_uint${size}_t *mem${op_operand}, tme_rwlock_t *rwlock, unsigned int align_min, unsigned int bus_boundary)"
        !           195:        echo "{"
        !           196:        echo "  const unsigned int host_boundary = TME_MEMORY_BUS_BOUNDARY;"
        !           197:        echo "  unsigned int size_skip;"
        !           198:        echo "  unsigned int size_done;"
        !           199:        if test ${op} = read; then
        !           200:            echo "  tme_uint${size}_t x;"
        !           201:        fi
        !           202: 
        !           203:        # emit the locals for the possible host boundaries:
        !           204:        #
        !           205:        host_boundary=${host_boundary_largest}
        !           206:        while test ${host_boundary} != 4; do
        !           207:            if test `expr ${host_boundary} \>= ${size_ifdef}` = 1; then
        !           208:                echo "#ifdef TME_HAVE_INT${host_boundary}_T"
        !           209:            fi
        !           210:            echo "  ${op_const}tme_shared tme_uint${host_boundary}_t *parts${host_boundary};"
        !           211:            echo "  tme_uint${host_boundary}_t part${host_boundary};"
        !           212:            if test ${op} = write; then
        !           213:                echo "  tme_uint${host_boundary}_t part${host_boundary}_cmp;"
        !           214:            fi
        !           215:            if test `expr ${host_boundary} \>= ${size_ifdef}` = 1; then
        !           216:                echo "#endif /* TME_HAVE_INT${host_boundary}_T */"
        !           217:            fi
        !           218:            host_boundary=`expr ${host_boundary} / 2`
        !           219:        done
        !           220:        echo ""
        !           221:        echo -n "  assert (bus_boundary != 0 && bus_boundary <= host_boundary);"
        !           222: 
        !           223:        # loop over the possible host boundaries:
        !           224:        #
        !           225:        host_boundary=${host_boundary_largest}
        !           226:        while test ${host_boundary} != 4; do
        !           227: 
        !           228:            # calculate the worst number of host boundaries that an
        !           229:            # access of this size could cross:
        !           230:            #
        !           231:            host_boundaries_worst=`expr ${size} - 16`
        !           232:            host_boundaries_worst=`expr ${host_boundaries_worst} / ${host_boundary}`
        !           233:            host_boundaries_worst=`expr ${host_boundaries_worst} + 1`
        !           234: 
        !           235:            # open this host boundary:
        !           236:            #
        !           237:            if test ${host_boundary} != 8; then
        !           238:                if test `expr ${host_boundary} \>= ${size_ifdef}` = 1; then
        !           239:                    echo ""
        !           240:                    echo ""
        !           241:                    echo "#ifdef TME_HAVE_INT${host_boundary}_T"
        !           242:                    echo ""
        !           243:                    echo -n " "
        !           244:                fi
        !           245:                echo -n " if (host_boundary == sizeof(tme_uint${host_boundary}_t))"
        !           246:            fi
        !           247:            echo " {"
        !           248: 
        !           249:            echo ""
        !           250:            echo "    /* prepare to ${op} the first ${host_boundary}-bit part of the memory: */"
        !           251:            echo "    parts${host_boundary} = (${op_const}tme_shared tme_uint${host_boundary}_t *) (((unsigned long) mem) & (((unsigned long) 0) - (${host_boundary} / 8)));"
        !           252:            echo "    size_skip = (((unsigned int) (unsigned long) mem) % (${host_boundary} / 8)) * 8;"
        !           253:            echo "    size_done = 0;"
        !           254: 
        !           255:            echo ""
        !           256:            echo "    /* ${op} the first ${host_boundary}-bit part of the memory: */"
        !           257: 
        !           258:            # emit two accesses.  if the worst number of boundaries
        !           259:            # that this access could cross is one, the second access
        !           260:            # is inside an if, else it's in a for loop:
        !           261:            #
        !           262:            indent0=
        !           263:            size_done=0
        !           264:            size_skip=size_skip
        !           265:            access_or=
        !           266:            while true; do
        !           267: 
        !           268:                # read this memory part:
        !           269:                #
        !           270:                echo "${indent0}    part${host_boundary} = tme_memory_atomic_read${host_boundary}(parts${host_boundary}, rwlock, sizeof(tme_uint${host_boundary}_t));"
        !           271: 
        !           272:                # if this is a read:
        !           273:                #
        !           274:                if test ${op} = read; then
        !           275: 
        !           276:                    echo ""
        !           277:                    echo "${indent0}    /* on a little-endian host, we shift off the skip"
        !           278:                    echo "${indent0}       data on the right, and shift the remaining data"
        !           279:                    echo "${indent0}       up into position in the result: */"
        !           280:                    echo "${indent0}    if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE) {"
        !           281:                    echo "${indent0}      x ${access_or}= (((tme_uint${size}_t) (part${host_boundary} >> ${size_skip})) << ${size_done});"
        !           282:                    echo "${indent0}    }"
        !           283:                    echo ""
        !           284:                    echo "${indent0}    /* on a big-endian host, we shift off the skip data"
        !           285:                    echo "${indent0}       on the left, and shift the remaining data down"
        !           286:                    echo "${indent0}       into position in the result: */"
        !           287:                    #
        !           288:                    # NB: on a big-endian host, because the skip data
        !           289:                    # is on the left, the type of what we shift
        !           290:                    # depends on how this host boundary size compares
        !           291:                    # to the access size:
        !           292:                    #
        !           293:                    echo "${indent0}    else {"
        !           294:                    echo -n "${indent0}      x ${access_or}= "
        !           295:                    if test `expr ${host_boundary} \> ${size}` = 1; then
        !           296:                        echo "((part${host_boundary} << ${size_skip}) >> ((${host_boundary} - ${size}) + ${size_done}));"
        !           297:                    else
        !           298:                        echo "((((tme_uint${size}_t) part${host_boundary}) << ((${size} - ${host_boundary}) + ${size_skip})) >> ${size_done});"
        !           299:                    fi
        !           300:                    echo "${indent0}    }"
        !           301: 
        !           302:                # otherwise, this is a write:
        !           303:                #
        !           304:                else
        !           305: 
        !           306:                    # start the compare-and-exchange do loop:
        !           307:                    #
        !           308:                    echo "${indent0}    do {"
        !           309:                    echo "${indent0}      part${host_boundary}_cmp = part${host_boundary};"
        !           310:                    echo ""
        !           311:                    echo "${indent0}      /* on a little-endian host, we clear with zeroes"
        !           312:                    echo "${indent0}         shifted up past the skip data, and then we"
        !           313:                    echo "${indent0}         insert the data shifted up past the skip data: */"
        !           314:                    echo "${indent0}      if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE) {"
        !           315:                    echo "${indent0}        part${host_boundary} &= (_tme_memory_type_mask(tme_uint${host_boundary}_t, + 0) ^ (((tme_uint${host_boundary}_t) _tme_memory_type_mask(tme_uint${size}_t, << ${size_done})) << ${size_skip}));"
        !           316:                    echo "${indent0}        part${host_boundary} |= (((tme_uint${host_boundary}_t) x) << ${size_skip});"
        !           317:                    echo "${indent0}      }"
        !           318:                    echo ""
        !           319:                    echo "${indent0}      /* on a big-endian host, we clear with zeroes"
        !           320:                    echo "${indent0}         shifted down past the skip data, and then we"
        !           321:                    echo "${indent0}         insert the data shifted down past the skip data: */"
        !           322:                    #
        !           323:                    # NB: on a big-endian host, because the skip data
        !           324:                    # is on the left, exactly how we shift depends on
        !           325:                    # how this host boundary size compares to the
        !           326:                    # access size:
        !           327:                    #
        !           328:                    echo "${indent0}      else {"
        !           329:                    if test `expr ${host_boundary} \> ${size}` = 1; then
        !           330:                        echo "${indent0}        part${host_boundary} &= ~((((tme_uint${host_boundary}_t) _tme_memory_type_mask(tme_uint${size}_t, + 0)) << ((${host_boundary} - ${size}) + ${size_done})) >> ${size_skip});"
        !           331:                        echo "${indent0}        part${host_boundary} |= ((((tme_uint${host_boundary}_t) x) << (${host_boundary} - ${size})) >> ${size_skip});"
        !           332:                    else
        !           333:                        echo "${indent0}        part${host_boundary} &= ~(_tme_memory_type_mask(tme_uint${host_boundary}_t, << ${size_done}) >> ${size_skip});"
        !           334:                        echo "${indent0}        part${host_boundary} |= (x >> ((${size} - ${host_boundary}) + ${size_skip}));"
        !           335:                    fi
        !           336:                    echo "${indent0}      }"
        !           337:                    echo ""
        !           338:                    echo "${indent0}      /* loop until we can atomically update this part: */"
        !           339:                    echo "${indent0}      part${host_boundary} = tme_memory_atomic_cx${host_boundary}(parts${host_boundary}, part${host_boundary}_cmp, part${host_boundary}, rwlock, sizeof(tme_uint${host_boundary}_t));"
        !           340:                    echo "${indent0}    } while (part${host_boundary} != part${host_boundary}_cmp);"
        !           341:                    if test ${host_boundaries_worst} != 1 || test ${size_skip} != 0; then
        !           342:                        echo "${indent0}    if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE) {"
        !           343:                        echo "${indent0}      x >>= (${host_boundary} - ${size_skip});"
        !           344:                        echo "${indent0}    }"
        !           345:                        echo "${indent0}    else {"
        !           346:                        echo "${indent0}      x <<= (${host_boundary} - ${size_skip});"
        !           347:                        echo "${indent0}    }"
        !           348:                    fi
        !           349:                fi
        !           350: 
        !           351:                # if this was the first access:
        !           352:                #
        !           353:                if test ${size_done} = 0; then
        !           354: 
        !           355:                    echo "    size_done = ${host_boundary} - size_skip;"
        !           356:                    size_done=size_done
        !           357:                    size_skip=0
        !           358:                    access_or='|'
        !           359: 
        !           360:                    # if the worst number of boundaries that this
        !           361:                    # access could cross is more than one, we will do
        !           362:                    # the remaining accesses in a loop, otherwise we
        !           363:                    # will do one more access, if necessary:
        !           364:                    #
        !           365:                    if test ${host_boundaries_worst} = 1; then
        !           366:                        access_if=true
        !           367:                    else
        !           368:                        access_if=false
        !           369: 
        !           370:                        # as an optimization, writes of full parts are
        !           371:                        # done directly:
        !           372:                        #
        !           373:                        if test ${op} = write; then
        !           374:                            if test `expr ${host_boundary} \< ${size}` = 1; then
        !           375:                                echo ""
        !           376:                                if test ${host_boundaries_worst} = 2; then
        !           377:                                    echo "    /* try to write one full ${host_boundary}-bit part of memory: */"
        !           378:                                    echo -n "    if (__tme_predict_true(size_done <= (${size} - ${host_boundary})))"
        !           379:                                else
        !           380:                                    echo "    /* write as many full ${host_boundary}-bit parts of the memory as we can: */"
        !           381:                                    echo -n "    for (; size_done <= (${size} - ${host_boundary}); )"
        !           382:                                fi
        !           383:                                echo " {"
        !           384:                                echo ""
        !           385:                                echo "      /* make a boundary: */"
        !           386:                                echo "      tme_memory_barrier(mem, (${size} / 8), TME_MEMORY_BARRIER_${op_cap}_BEFORE_${op_cap});"
        !           387:                                echo ""
        !           388:                                echo "      /* write a full ${host_boundary}-bit part of memory: */"
        !           389:                                echo "      part${host_boundary} = (x >> ((TME_ENDIAN_NATIVE == TME_ENDIAN_BIG) * (${size} - ${host_boundary})));"
        !           390:                                echo "      parts${host_boundary}++;"
        !           391:                                echo "      tme_memory_atomic_write${host_boundary}(parts${host_boundary}, part${host_boundary}, rwlock, sizeof(tme_uint${host_boundary}_t));"
        !           392:                                echo "      size_done += ${host_boundary};"
        !           393:                                echo "      if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE) {"
        !           394:                                echo "        x >>= ${host_boundary};"
        !           395:                                echo "      }"
        !           396:                                echo "      else {"
        !           397:                                echo "        x <<= ${host_boundary};"
        !           398:                                echo "      }"
        !           399:                                echo "    }"
        !           400:                                access_if=true
        !           401:                            fi
        !           402:                        fi
        !           403:                    fi
        !           404:                    echo ""
        !           405:                    if $access_if; then
        !           406:                        echo "    /* ${op} at most one remaining ${host_boundary}-bit part of the memory: */"
        !           407:                        echo -n "    if (__tme_predict_false(size_done < ${size}))"
        !           408:                    else
        !           409:                        echo "    /* ${op} any remaining ${host_boundary}-bit parts of the memory: */"
        !           410:                        echo -n "    for (; size_done < ${size}; size_done += ${host_boundary})"
        !           411:                    fi
        !           412:                    echo " {"
        !           413: 
        !           414:                    echo ""
        !           415:                    echo "      /* make a boundary: */"
        !           416:                    echo "      tme_memory_barrier(mem, (${size} / 8), TME_MEMORY_BARRIER_${op_cap}_BEFORE_${op_cap});"
        !           417:                    echo ""
        !           418:                    echo "      /* ${op} the next ${host_boundary}-bit part of the memory: */"
        !           419:                    echo "      parts${host_boundary}++;"
        !           420:                    indent0="  "
        !           421: 
        !           422:                # otherwise, this was the loop or second access:
        !           423:                #
        !           424:                else
        !           425:                    echo "    }"
        !           426:                    break
        !           427:                fi
        !           428: 
        !           429:            done
        !           430: 
        !           431:            echo "  }"
        !           432: 
        !           433:            # close this host boundary:
        !           434:            #
        !           435:            if test ${host_boundary} != 8; then
        !           436:                echo ""
        !           437:                echo -n "  else"
        !           438:                if test `expr ${host_boundary} \>= ${size_ifdef}` = 1; then
        !           439:                    echo ""
        !           440:                    echo ""
        !           441:                    echo -n "#endif /* TME_HAVE_INT${host_boundary}_T */"
        !           442:                    if test ${host_boundary} = ${size_ifdef}; then
        !           443:                        echo ""
        !           444:                        echo ""
        !           445:                        echo -n " "
        !           446:                    fi
        !           447:                fi
        !           448:            fi
        !           449: 
        !           450:            # advance:
        !           451:            #
        !           452:            host_boundary=`expr ${host_boundary} / 2`
        !           453:        done
        !           454:        if test ${op} = read; then
        !           455:            echo ""
        !           456:            echo "  /* return the value read: */"
        !           457:            echo "  return (x);"
        !           458:        fi
        !           459:        echo "}"
        !           460:     done
        !           461: 
        !           462:     if test `expr ${size} \>= ${size_ifdef}` = 1; then
        !           463:        echo ""
        !           464:        echo "#endif /* TME_HAVE_INT${size}_T */"
        !           465:     fi
        !           466: 
        !           467: done
        !           468: 
        !           469: # emit the bus read and write buffer functions:
        !           470: #
        !           471: for op in read write; do
        !           472: 
        !           473:     # dispatch on the operation:
        !           474:     #
        !           475:     if test ${op} = read; then
        !           476:        op_cap=READ
        !           477:        op_rwlock=rd
        !           478:        op_const_mem="_tme_const "
        !           479:        op_const_buffer=
        !           480:        op_audit_mem=
        !           481:        op_audit_buffer=_tme_audit_pointer
        !           482:        op_memcpy="(buffer), ((_tme_const tme_uint8_t *) (mem))"
        !           483:        op_copy="*buffer = *part_buffer"
        !           484:     else
        !           485:        op_cap=WRITE
        !           486:        op_rwlock=wr
        !           487:        op_const_mem=
        !           488:        op_const_buffer="_tme_const "
        !           489:        op_audit_mem=_tme_audit_pointer_shared
        !           490:        op_audit_buffer=_tme_audit_pointer_const
        !           491:        op_memcpy="(tme_uint8_t *) (mem), (buffer)"
        !           492:        op_copy="*part_buffer = *buffer"
        !           493:     fi
        !           494: 
        !           495:     # if we're making the header:
        !           496:     #
        !           497:     if $header; then
        !           498: 
        !           499:        echo ""
        !           500:        echo "/* the bus ${op} buffer function and default macro implementation: */"
        !           501: 
        !           502:        # emit the prototype:
        !           503:        #
        !           504:        echo "void tme_memory_bus_${op}_buffer _TME_P((${op_const_mem}tme_shared tme_uint8_t *, ${op_const_buffer}tme_uint8_t *, unsigned long, tme_rwlock_t *, unsigned int, unsigned int));"
        !           505: 
        !           506:        # emit the default macro definition:
        !           507:        #
        !           508:        echo "#define tme_memory_bus_${op}_buffer(mem, buffer, count, rwlock, align_min, bus_boundary) \\"
        !           509:        echo "  do { \\"
        !           510:        echo "    if (TME_THREADS_COOPERATIVE) { \\"
        !           511:        echo "      memcpy(${op_memcpy}, (count)); \\"
        !           512:        echo "    } \\"
        !           513:        echo "    else { \\"
        !           514:        echo "      tme_memory_bus_${op}_buffer(((${op_const_mem}tme_shared tme_uint8_t *) ${op_audit_mem}(mem)), ((${op_const_buffer}tme_uint8_t *) ${op_audit_buffer}(buffer)), (count), (rwlock), (align_min), (bus_boundary)); \\"
        !           515:        echo "    } \\"
        !           516:        echo "  } while (/* CONSTCOND */ 0)"
        !           517: 
        !           518:        continue
        !           519:     fi
        !           520: 
        !           521:     # start the function:
        !           522:     #
        !           523:     echo ""
        !           524:     echo "/* undefine the macro version of tme_memory_bus_${op}_buffer: */"
        !           525:     echo "#undef tme_memory_bus_${op}_buffer"
        !           526:     echo ""
        !           527:     echo "/* the bus ${op} buffer function: */"
        !           528:     echo "void"
        !           529:     echo "tme_memory_bus_${op}_buffer(${op_const_mem}tme_shared tme_uint8_t *mem, ${op_const_buffer}tme_uint8_t *buffer, unsigned long count, tme_rwlock_t *rwlock, unsigned int align_min, unsigned int bus_boundary)"
        !           530:     echo "{"
        !           531:     echo "  const unsigned int host_boundary = TME_MEMORY_BUS_BOUNDARY;"
        !           532:     echo "  ${op_const_mem}tme_uint8_t *part_buffer;"
        !           533:     echo "  unsigned int count_done;"
        !           534:     echo "  unsigned int count_misaligned;"
        !           535:     echo "  unsigned int bits_misaligned;"
        !           536: 
        !           537:     # emit the locals for the possible host boundaries:
        !           538:     #
        !           539:     host_boundary=${host_boundary_largest}
        !           540:     while test ${host_boundary} != 4; do
        !           541:        if test `expr ${host_boundary} \>= ${size_ifdef}` = 1; then
        !           542:            echo "#ifdef TME_HAVE_INT${host_boundary}_T"
        !           543:        fi
        !           544:        echo "  ${op_const}tme_shared tme_uint${host_boundary}_t *parts${host_boundary};"
        !           545:        echo "  tme_uint${host_boundary}_t part${host_boundary}_buffer;"
        !           546:        echo "  tme_uint${host_boundary}_t part${host_boundary};"
        !           547:        echo "  tme_uint${host_boundary}_t part${host_boundary}_next;"
        !           548:        if test ${op} = write; then
        !           549:            echo "  tme_uint${host_boundary}_t part${host_boundary}_mask;"
        !           550:            echo "  tme_uint${host_boundary}_t part${host_boundary}_cmp;"
        !           551:        fi
        !           552:        if test `expr ${host_boundary} \>= ${size_ifdef}` = 1; then
        !           553:            echo "#endif /* TME_HAVE_INT${host_boundary}_T */"
        !           554:        fi
        !           555:        host_boundary=`expr ${host_boundary} / 2`
        !           556:     done
        !           557:     echo ""
        !           558:     echo "  assert (count != 0);"
        !           559:     echo "  assert (bus_boundary != 0);"
        !           560:     
        !           561:     echo ""
        !           562:     echo "  /* if we are locking for all memory accesses, lock memory"
        !           563:     echo "     around a memcpy: */"
        !           564:     echo "  if (TME_MEMORY_ALIGNMENT_ATOMIC(TME_MEMORY_TYPE_COMMON) == 0) {"
        !           565:     echo "    tme_rwlock_${op_rwlock}lock(rwlock);"
        !           566:     echo "    memcpy(${op_memcpy}, (count));"
        !           567:     echo "    tme_rwlock_unlock(rwlock);"
        !           568:     echo "  }"
        !           569:     echo ""
        !           570:     echo "  /* otherwise, if the emulated bus boundary is greater than the"
        !           571:     echo "     host's bus boundary, we are forced to stop all other threads"
        !           572:     echo "     around a memcpy: */"
        !           573:     echo "  else if (__tme_predict_false(bus_boundary == 0"
        !           574:     echo "                               || bus_boundary > host_boundary)) {"
        !           575:     echo "    tme_thread_suspend_others();"
        !           576:     echo "    memcpy(${op_memcpy}, (count) + (0 && align_min));"
        !           577:     echo "    tme_thread_resume_others();"
        !           578:     echo "  }"
        !           579: 
        !           580:     # loop over the possible host boundaries:
        !           581:     #
        !           582:     host_boundary=${host_boundary_largest}
        !           583:     indent0=
        !           584:     while test ${host_boundary} != 4; do
        !           585: 
        !           586:        # open this host boundary:
        !           587:        #
        !           588:        if test `expr ${host_boundary} \>= ${size_ifdef}` = 1; then
        !           589:            echo ""
        !           590:            echo "#ifdef TME_HAVE_INT${host_boundary}_T"
        !           591:        fi
        !           592:        echo ""
        !           593:        echo -n "  else"
        !           594:        if test ${host_boundary} != 8; then
        !           595:            echo -n " if (host_boundary == sizeof(tme_uint${host_boundary}_t))"
        !           596:        fi
        !           597:        echo " {"
        !           598: 
        !           599:        if test ${op} = write; then
        !           600:            op_part_read="tme_memory_read${host_boundary}((const tme_uint${host_boundary}_t *) buffer, sizeof(tme_uint${host_boundary}_t))"
        !           601:            op_part_write="tme_memory_atomic_write${host_boundary}(parts${host_boundary}, part${host_boundary}, rwlock, sizeof(tme_uint${host_boundary}_t))"
        !           602:        else
        !           603:            op_part_read="tme_memory_atomic_read${host_boundary}(parts${host_boundary}, rwlock, sizeof(tme_uint${host_boundary}_t))"
        !           604:            op_part_write="tme_memory_write${host_boundary}((tme_uint${host_boundary}_t *) buffer, part${host_boundary}, sizeof(tme_uint${host_boundary}_t))"
        !           605:        fi
        !           606: 
        !           607:        echo ""
        !           608:        echo "    /* make a ${host_boundary}-bit pointer to the memory: */"
        !           609:        echo "    parts${host_boundary} = (${op_const}tme_shared tme_uint${host_boundary}_t *) mem;"
        !           610:        echo ""
        !           611:        echo "    /* if this pointer is not ${host_boundary}-bit aligned: */"
        !           612:        echo "    if (__tme_predict_false((((unsigned long) parts${host_boundary}) % sizeof(tme_uint${host_boundary}_t)) != 0)) {"
        !           613:        echo ""
        !           614:        echo "      /* get the misalignment from the previous ${host_boundary}-bit boundary: */"
        !           615:        echo "      count_misaligned = ((unsigned long) parts${host_boundary}) % sizeof(tme_uint${host_boundary}_t);"
        !           616:        echo ""
        !           617:        echo "      /* truncate this pointer to the previous ${host_boundary}-bit boundary: */"
        !           618:        echo "      parts${host_boundary} = (${op_const}tme_shared tme_uint${host_boundary}_t *) (((unsigned long) parts${host_boundary}) & (((unsigned long) 0) - sizeof(tme_uint${host_boundary}_t)));"
        !           619:        echo ""
        !           620:        echo "      /* get the number of bytes to ${op} in the first ${host_boundary}-bit memory part: */"
        !           621:        echo "      count_done = sizeof(tme_uint${host_boundary}_t) - count_misaligned;"
        !           622:        echo "      if (__tme_predict_false(count_done > count)) {"
        !           623:        echo "        count_done = count;"
        !           624:        echo "      }"
        !           625: 
        !           626:        if test ${op} = write; then
        !           627:            echo ""
        !           628:            echo "      /* make a mask that clears for the data to write in the"
        !           629:            echo "         first ${host_boundary}-bit memory part: */"
        !           630:            echo "      part${host_boundary}_mask = 1;"
        !           631:            echo "      part${host_boundary}_mask = (part${host_boundary}_mask << (count_done * 8)) - 1;"
        !           632:            echo "      part${host_boundary}_mask"
        !           633:            echo "        <<= (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE"
        !           634:            echo "             ? (count_misaligned * 8)"
        !           635:            echo "             : (${host_boundary} - ((count_misaligned + count_done) * 8)));"
        !           636:            echo "      part${host_boundary}_mask = ~part${host_boundary}_mask;"
        !           637:            echo ""
        !           638:            echo "      /* copy from the buffer the bytes to write in the first"
        !           639:            echo "         ${host_boundary}-bit memory part: */"
        !           640:            echo "      part${host_boundary}_buffer = 0;"
        !           641:        else
        !           642:            echo ""
        !           643:            echo "      /* read the first ${host_boundary}-bit memory part: */"
        !           644:            echo "      part${host_boundary}_buffer = ${op_part_read};"
        !           645:            echo "      parts${host_boundary}++;"
        !           646:            echo ""
        !           647:            echo "      /* copy to the buffer the bytes to read in the first"
        !           648:            echo "         ${host_boundary}-bit memory part: */"
        !           649:        fi
        !           650:        echo "      part_buffer = ((tme_uint8_t *) &part${host_boundary}_buffer) + count_misaligned;"
        !           651:        echo "      count -= count_done;"
        !           652:        echo "      do {"
        !           653:        echo "        ${op_copy};"
        !           654:        echo "        part_buffer++;"
        !           655:        echo "        buffer++;"
        !           656:        echo "      } while (--count_done != 0);"
        !           657: 
        !           658:        if test ${op} = write; then
        !           659:            echo ""
        !           660:            echo "      /* compare-and-exchange the first ${host_boundary}-bit memory part: */"
        !           661:            echo "      part${host_boundary} = ${op_part_read};"
        !           662:            echo "      do {"
        !           663:            echo "        part${host_boundary}_cmp = part${host_boundary};"
        !           664:            echo "        part${host_boundary} = (part${host_boundary} & part${host_boundary}_mask) | part${host_boundary}_buffer;"
        !           665:            echo "        part${host_boundary} = tme_memory_atomic_cx${host_boundary}(parts${host_boundary}, part${host_boundary}_cmp, part${host_boundary}, rwlock, sizeof(tme_uint${host_boundary}_t));"
        !           666:            echo "      } while (part${host_boundary} != part${host_boundary}_cmp);"
        !           667:            echo "      parts${host_boundary}++;"
        !           668:        fi
        !           669:        echo "    }"
        !           670: 
        !           671:        echo ""
        !           672:        echo "    /* if we have full ${host_boundary}-bit parts to ${op}: */"
        !           673:        echo "    if (__tme_predict_true(count >= sizeof(tme_uint${host_boundary}_t))) {"
        !           674:        echo ""
        !           675:        echo "      /* if the buffer is ${host_boundary}-bit aligned: */"
        !           676:        echo "      if (__tme_predict_true((((unsigned long) buffer) % sizeof(tme_uint${host_boundary}_t)) == 0)) {"
        !           677:        echo ""
        !           678:        echo "        /* ${op} full ${host_boundary}-bit parts without shifting: */"
        !           679:        echo "        do {"
        !           680:        echo "          part${host_boundary} = ${op_part_read};"
        !           681:        echo "          ${op_part_write};"
        !           682:        echo ""
        !           683:        echo "          /* advance: */"
        !           684:        echo "          parts${host_boundary}++;"
        !           685:        echo "          buffer += sizeof(tme_uint${host_boundary}_t);"
        !           686:        echo "          count -= sizeof(tme_uint${host_boundary}_t);"
        !           687:        echo "        } while (count >= sizeof(tme_uint${host_boundary}_t));"
        !           688:        echo "      }"
        !           689:        echo ""
        !           690:        echo "      /* otherwise, the buffer is not ${host_boundary}-bit aligned: */"
        !           691:        echo "      else {"
        !           692:        echo ""
        !           693:        echo "        /* get the misalignment to the next ${host_boundary}-bit boundary: */"
        !           694:        echo "        count_misaligned = (sizeof(tme_uint${host_boundary}_t) - ((unsigned int) (unsigned long) buffer)) % sizeof(tme_uint${host_boundary}_t);"
        !           695:        if test ${op} = write; then
        !           696:            echo ""
        !           697:            echo "        /* copy from the buffer until it is aligned: */"
        !           698:            echo "        part${host_boundary}_buffer = 0;"
        !           699:        else
        !           700:            echo ""
        !           701:            echo "        /* read the next ${host_boundary}-bit memory part: */"
        !           702:            echo "        part${host_boundary}_buffer = ${op_part_read};"
        !           703:            echo "        parts${host_boundary}++;"
        !           704:            echo ""
        !           705:            echo "        /* copy to the buffer until it is aligned: */"
        !           706:        fi
        !           707:        echo "        part_buffer = ((${op_const_mem}tme_uint8_t *) &part${host_boundary}_buffer);"
        !           708:        echo "        count_done = count_misaligned;"
        !           709:        echo "        count -= count_misaligned;"
        !           710:        echo "        do {"
        !           711:        echo "          ${op_copy};"
        !           712:        echo "          part_buffer++;"
        !           713:        echo "          buffer++;"
        !           714:        echo "        } while (--count_done != 0);"
        !           715: 
        !           716:        echo ""
        !           717:        echo "        /* ${op} full ${host_boundary}-bit words with shifting: */"
        !           718:        echo "        bits_misaligned = count_misaligned * 8;"
        !           719:        if test ${op} = write; then
        !           720:            op_shift=bits_misaligned
        !           721:            op_shift_next="(${host_boundary} - bits_misaligned)"
        !           722:            echo "        part${host_boundary} = part${host_boundary}_buffer;"
        !           723:        else
        !           724:            op_shift="(${host_boundary} - bits_misaligned)"
        !           725:            op_shift_next=bits_misaligned
        !           726:            echo "        part${host_boundary}"
        !           727:            echo "          = (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE"
        !           728:            echo "             ? (part${host_boundary}_buffer >> ${op_shift_next})"
        !           729:            echo "             : (part${host_boundary}_buffer << ${op_shift_next}));"
        !           730:        fi
        !           731:        echo "        for (; count >= sizeof(tme_uint${host_boundary}_t); ) {"
        !           732:        echo "          part${host_boundary}_next = ${op_part_read};"
        !           733:        echo "          if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE) {"
        !           734:        echo "            part${host_boundary} |= (part${host_boundary}_next << ${op_shift});"
        !           735:        echo "            ${op_part_write};"
        !           736:        echo "            part${host_boundary} = (part${host_boundary}_next >> ${op_shift_next});"
        !           737:        echo "          }"
        !           738:        echo "          else {"
        !           739:        echo "            part${host_boundary} |= (part${host_boundary}_next >> ${op_shift});"
        !           740:        echo "            ${op_part_write};"
        !           741:        echo "            part${host_boundary} = (part${host_boundary}_next << ${op_shift_next});"
        !           742:        echo "          }"
        !           743:        echo ""
        !           744:        echo "          /* advance: */"
        !           745:        echo "          parts${host_boundary}++;"
        !           746:        echo "          buffer += sizeof(tme_uint${host_boundary}_t);"
        !           747:        echo "          count -= sizeof(tme_uint${host_boundary}_t);"
        !           748:        echo "        }"
        !           749: 
        !           750:        echo ""
        !           751:        echo "        /* calculate how many more bytes there are to ${op} in this"
        !           752:        echo "           ${host_boundary}-bit memory part: */"
        !           753:        echo "        count_done = sizeof(tme_uint${host_boundary}_t) - count_misaligned;"
        !           754:        echo "        part${host_boundary}_buffer = part${host_boundary};"
        !           755:        if test ${op} = write; then
        !           756:            echo ""
        !           757:            echo "        /* if we can't write one more full ${host_boundary}-bit memory part: */"
        !           758:            echo "        if (count_done > count) {"
        !           759:            echo ""
        !           760:            echo "          /* we will reread this data to write below: */"
        !           761:            echo "          buffer -= count_misaligned;"
        !           762:            echo "          count += count_misaligned;"
        !           763:            echo "        }"
        !           764:            echo ""
        !           765:            echo "        /* otherwise, we can write one more full ${host_boundary}-bit memory part: */"
        !           766:            echo "        else {"
        !           767:            echo ""
        !           768:            echo "          /* copy from the buffer until we have the full ${host_boundary}-bit part: */"
        !           769:            echo "          part_buffer = ((${op_const_mem}tme_uint8_t *) &part${host_boundary}_buffer) + count_misaligned;"
        !           770:            echo "          count -= count_done;"
        !           771:            echo "          do {"
        !           772:            echo "            ${op_copy};"
        !           773:            echo "            part_buffer++;"
        !           774:            echo "            buffer++;"
        !           775:            echo "          } while (--count_done != 0);"
        !           776:            echo ""
        !           777:            echo "          /* write the last full ${host_boundary}-bit memory part: */"
        !           778:            echo "          part${host_boundary} = part${host_boundary}_buffer;"
        !           779:            echo "          ${op_part_write};"
        !           780:            echo "        }"
        !           781:        else
        !           782:            echo ""
        !           783:            echo "        /* copy to the buffer the remaining bytes in this ${host_boundary}-bit part: */"
        !           784:            echo "        if (count_done > count) {"
        !           785:            echo "          count_done = count;"
        !           786:            echo "        }"
        !           787:            echo "        part_buffer = ((${op_const_mem}tme_uint8_t *) &part${host_boundary}_buffer);"
        !           788:            echo "        count -= count_done;"
        !           789:            echo "        do {"
        !           790:            echo "          ${op_copy};"
        !           791:            echo "          part_buffer++;"
        !           792:            echo "          buffer++;"
        !           793:            echo "        } while (--count_done != 0);"
        !           794:        fi
        !           795:        echo "      }"
        !           796:        echo "    }"
        !           797: 
        !           798:        echo ""
        !           799:        echo "    /* if we still have bytes to ${op}: */"
        !           800:        echo "    if (__tme_predict_false(count > 0)) {"
        !           801:        echo ""
        !           802:        echo "      /* we must have less than a full ${host_boundary}-bit part to ${op}: */"
        !           803:        echo "      assert (count < sizeof(tme_uint${host_boundary}_t));"
        !           804:        if test ${op} = write; then
        !           805:            echo ""
        !           806:            echo "      /* make a mask that clears for the data to write in the last"
        !           807:            echo "         ${host_boundary}-bit memory part: */"
        !           808:            echo "      part${host_boundary}_mask"
        !           809:            echo "        = (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE"
        !           810:            echo "           ? _tme_memory_type_mask(tme_uint${host_boundary}_t, << (count * 8))"
        !           811:            echo "           : _tme_memory_type_mask(tme_uint${host_boundary}_t, >> (count * 8)));"
        !           812:            echo ""
        !           813:            echo "      /* copy from the buffer the bytes to write in the last"
        !           814:            echo "         ${host_boundary}-bit memory part: */"
        !           815:            echo "      part${host_boundary}_buffer = 0;"
        !           816:        else
        !           817:            echo ""
        !           818:            echo "      /* read the last ${host_boundary}-bit memory part: */"
        !           819:            echo "      part${host_boundary}_buffer = ${op_part_read};"
        !           820:            echo ""
        !           821:            echo "      /* copy to the buffer the bytes to read in the first"
        !           822:            echo "         ${host_boundary}-bit memory part: */"
        !           823:        fi
        !           824:        echo "      part_buffer = ((${op_const_mem}tme_uint8_t *) &part${host_boundary}_buffer);"
        !           825:        echo "      count_done = count;"
        !           826:        echo "      do {"
        !           827:        echo "        ${op_copy};"
        !           828:        echo "        part_buffer++;"
        !           829:        echo "        buffer++;"
        !           830:        echo "      } while (--count_done != 0);"
        !           831:        if test ${op} = write; then
        !           832:            echo ""
        !           833:            echo "      /* compare-and-exchange the last ${host_boundary}-bit memory part: */"
        !           834:            echo "      part${host_boundary} = ${op_part_read};"
        !           835:            echo "      do {"
        !           836:            echo "        part${host_boundary}_cmp = part${host_boundary};"
        !           837:            echo "        part${host_boundary} = (part${host_boundary} & part${host_boundary}_mask) | part${host_boundary}_buffer;"
        !           838:            echo "        part${host_boundary} = tme_memory_atomic_cx${host_boundary}(parts${host_boundary}, part${host_boundary}_cmp, part${host_boundary}, rwlock, sizeof(tme_uint${host_boundary}_t));"
        !           839:            echo "      } while (part${host_boundary} != part${host_boundary}_cmp);"
        !           840:        fi
        !           841:        echo "    }"
        !           842:        
        !           843:        # close this host boundary:
        !           844:        #
        !           845:        echo ""
        !           846:        echo "  }"
        !           847:        if test `expr ${host_boundary} \>= ${size_ifdef}` = 1; then
        !           848:            echo ""
        !           849:            echo "#endif /* TME_HAVE_INT${host_boundary}_T */"
        !           850:        fi
        !           851: 
        !           852:        # advance:
        !           853:        #
        !           854:        host_boundary=`expr ${host_boundary} / 2`
        !           855:     done
        !           856: 
        !           857:     echo "}"
        !           858: done
        !           859: 
        !           860: # permute for the different sizes:
        !           861: #
        !           862: for size in ${sizes}; do
        !           863: 
        !           864:     if test `expr ${size} \>= ${size_ifdef}` = 1; then
        !           865:        echo ""
        !           866:        echo "#ifdef TME_HAVE_INT${size}_T"
        !           867:     fi
        !           868: 
        !           869:     # permute for the different types of memory read and write macros.
        !           870:     # all of these macros work with memory of any alignment, but for
        !           871:     # best performance they accept the minimum alignment of the memory
        !           872:     # known at compile time.
        !           873:     #
        !           874:     # the "plain" macros are used to read and write memory that is not
        !           875:     # shared.
        !           876:     #
        !           877:     # the "atomic" macros are used to read and write memory that is
        !           878:     # shared.  the total read or write is always atomic.
        !           879:     # 
        !           880:     # the "bus" macros are used to read and write memory that is
        !           881:     # shared, with the access split across the given bus boundary into
        !           882:     # atomic partials.
        !           883:     #
        !           884:     for type_user in plain atomic bus; do
        !           885: 
        !           886:        # permute over read and write:
        !           887:        #
        !           888:        for op in read write; do
        !           889: 
        !           890:            # these macros are for the header file, and there are
        !           891:            # hand-coded macros for 8-bit values:
        !           892:            #
        !           893:            if $header; then :; else continue; fi
        !           894:            if test ${size} = 8; then continue; fi
        !           895: 
        !           896:            # characterize this macro:
        !           897:            #
        !           898:            type="_${type_user}"
        !           899:            type_lock=", lock"
        !           900:            type_part=_atomic
        !           901:            type_bus_boundary=
        !           902:            case ${type_user} in
        !           903:            plain)
        !           904:                type=
        !           905:                type_lock=
        !           906:                type_part=
        !           907:                ;;
        !           908:            bus)
        !           909:                type_bus_boundary=", bus_boundary"
        !           910:                ;;
        !           911:            esac
        !           912:            if test ${op} = read; then
        !           913:                op_x=
        !           914:                op_open="  ( \\"
        !           915:                op_indent0="   "
        !           916:                op_indent1=${op_indent0}
        !           917:                op_then="${op_indent1}? \\"
        !           918:                op_else_if="${op_indent1}: \\"
        !           919:                op_else=${op_else_if}
        !           920:                op_indent2="${op_indent1}  "
        !           921:                op_semi=
        !           922:                op_close="  )"
        !           923:            else
        !           924:                op_x=", x"
        !           925:                op_open="  do { \\@    if \\"
        !           926:                op_indent0="      "
        !           927:                op_indent1=${op_indent0}
        !           928:                op_then="      { \\"
        !           929:                op_else_if="      } \\@    else if \\"
        !           930:                op_else="      } \\@    else \\@${op_then}"
        !           931:                op_indent2="        "
        !           932:                op_semi=';'
        !           933:                op_close="      } \\@  } while (/* CONSTCOND */ 0)"
        !           934:            fi
        !           935: 
        !           936:            # start the macro:
        !           937:            #
        !           938:            echo ""
        !           939:            echo "/* the default ${size}-bit memory ${type_user} ${op} macro: */"
        !           940:            echo "#define tme_memory${type}_${op}${size}(mem${op_x}${type_lock}, align_min${type_bus_boundary}) \\"
        !           941:            echo "${op_open}" | tr '@' '\n'
        !           942: 
        !           943:            # dispatch on the macro type:
        !           944:            #
        !           945:            case ${type_user} in
        !           946: 
        !           947:            plain)
        !           948:                echo "${op_indent0}/* if we know at compile time that the memory is aligned \\"
        !           949:                echo "${op_indent0}   enough to ${op} directly, do the single direct ${op}. \\"
        !           950:                echo "${op_indent0}\\"
        !           951:                echo "${op_indent0}   otherwise, if we know at compile time that the memory \\"
        !           952:                echo "${op_indent0}   is less aligned than the smallest acceptable parts size, \\"
        !           953:                echo "${op_indent0}   test if the memory is aligned enough to ${op} directly, \\"
        !           954:                echo "${op_indent0}   and do the single direct ${op} if it is: */ \\"
        !           955:                echo "${op_indent0}(__tme_predict_true((_TME_ALIGNOF_INT${size}_T == 1 \\"
        !           956:                echo "${op_indent0}                     || (align_min) >= _TME_ALIGNOF_INT${size}_T) \\"
        !           957:                echo "${op_indent0}                    || ((align_min) < TME_MEMORY_ALIGNMENT_ACCEPT(tme_uint${size}_t) \\"
        !           958:                echo "${op_indent0}                        && _tme_memory_address_test(mem, _TME_ALIGNOF_INT${size}_T - 1, align_min) == 0))) \\"
        !           959:                echo "${op_then}"
        !           960:                echo "${op_indent2}_tme_memory_${op}(tme_uint${size}_t, tme_uint${size}_t, mem, 0${op_x})${op_semi} \\"
        !           961: 
        !           962:                # loop over the possible part sizes:
        !           963:                #
        !           964:                size_part=8
        !           965:                while test ${size_part} != ${size}; do
        !           966: 
        !           967:                    # at this point, we know that the memory is at
        !           968:                    # least aligned to the part size:
        !           969:                    #
        !           970: 
        !           971:                    # if this is the last possible part size:
        !           972:                    #
        !           973:                    if test `expr ${size_part} \* 2` = ${size}; then
        !           974: 
        !           975:                        # we will just access all parts of this size:
        !           976:                        #
        !           977:                        echo "${op_else}" | tr '@' '\n'
        !           978: 
        !           979:                    # otherwise, this is not the last possible part
        !           980:                    # size:
        !           981:                    #
        !           982:                    else
        !           983: 
        !           984:                        # if we know at compile time that accessing
        !           985:                        # all parts of this size is acceptable over
        !           986:                        # further testing of the address, and the
        !           987:                        # memory is not more aligned than this part
        !           988:                        # size, we will just access all parts of this
        !           989:                        # size:
        !           990:                        #
        !           991:                        echo "${op_else_if}" | tr '@' '\n'
        !           992:                        echo "${op_indent1}((TME_MEMORY_ALIGNMENT_ACCEPT(tme_uint${size}_t) <= sizeof(tme_uint${size_part}_t)) \\"
        !           993:                        echo "${op_indent1} && ((align_min) <= sizeof(tme_uint${size_part}_t))) \\"
        !           994:                        echo "${op_then}"
        !           995:                    fi
        !           996: 
        !           997:                    # we always emit one set of partial accesses, all
        !           998:                    # of this part size.
        !           999:                    #
        !          1000:                    # then, if this isn't the last possible part size,
        !          1001:                    # we test if the address is aligned only to this
        !          1002:                    # part size.  if it is, we emit a second set of partial
        !          1003:                    # accesses, to transfer this part size, some number 
        !          1004:                    # of parts of the next part size, and one part of this
        !          1005:                    # part size:
        !          1006:                    #
        !          1007:                    size_now=${size_part}
        !          1008:                    misaligned=false
        !          1009:                    while true; do
        !          1010:                        size_done=0
        !          1011:                        while test ${size_done} != ${size}; do
        !          1012: 
        !          1013:                            # emit one partial transfer:
        !          1014:                            #
        !          1015:                            echo -n "${op_indent2}"
        !          1016:                            op_delim=${op_semi}
        !          1017:                            if test ${op} = read; then
        !          1018:                                if test ${size_done} = 0; then echo -n '('; else echo -n ' | '; fi
        !          1019:                                if test `expr ${size_done} + ${size_now}` = ${size}; then op_delim=')'; fi
        !          1020:                            fi
        !          1021:                            echo "_tme_memory${type}_${op}(tme_uint${size}_t, tme_uint${size_now}_t, mem, (${size_done} / 8)${op_x})${op_delim} \\"
        !          1022: 
        !          1023:                            # advance:
        !          1024:                            #
        !          1025:                            size_done=`expr ${size_done} + ${size_now}`
        !          1026:                            size_now=`expr ${size} - ${size_done}`
        !          1027:                            if test `expr ${size_now} \> ${size_part}` = 1; then
        !          1028:                                size_now=${size_part}
        !          1029:                            fi
        !          1030:                        done
        !          1031: 
        !          1032:                        # if we have already done the misaligned set,
        !          1033:                        # stop now:
        !          1034:                        #
        !          1035:                        if ${misaligned}; then
        !          1036:                            break
        !          1037:                        fi
        !          1038:                        misaligned=true
        !          1039: 
        !          1040:                        # advance to test and do the misaligned set:
        !          1041:                        #
        !          1042:                        size_now=${size_part}
        !          1043:                        size_part=`expr ${size_part} \* 2`
        !          1044:                        if test ${size_part} = ${size}; then
        !          1045:                            break
        !          1046:                        fi
        !          1047:                        echo "${op_else_if}" | tr '@' '\n'
        !          1048:                        echo "${op_indent1}(_tme_memory_address_test(mem, sizeof(tme_uint${size_now}_t), align_min) != 0) \\"
        !          1049:                        echo "${op_then}"
        !          1050:                    done
        !          1051:                done
        !          1052:                ;;
        !          1053: 
        !          1054:            atomic)
        !          1055:                echo "${op_indent0}/* if we aren't locking for all memory accesses, and we can \\"
        !          1056:                echo "${op_indent0}   make direct ${size}-bit accesses, and this memory is aligned \\"
        !          1057:                echo "${op_indent0}   enough to make a single direct atomic access, do the single \\"
        !          1058:                echo "${op_indent0}   direct atomic ${op}: */ \\"
        !          1059:                echo "${op_indent0}(__tme_predict_true(TME_MEMORY_ALIGNMENT_ATOMIC(TME_MEMORY_TYPE_COMMON) != 0 \\"
        !          1060:                echo "${op_indent0}                    && TME_MEMORY_ALIGNMENT_ATOMIC(tme_uint${size}_t) != 0 \\"
        !          1061:                echo "${op_indent0}                    && _tme_memory_address_test(mem, TME_MEMORY_ALIGNMENT_ATOMIC(tme_uint${size}_t) - 1, align_min) == 0)) \\"
        !          1062:                echo "${op_then}"
        !          1063:                echo "${op_indent2}(*_tme_audit_type(mem, tme_uint${size}_t *)) \\"
        !          1064:                if test ${op} = write; then
        !          1065:                    echo "${op_indent2}  = (x); \\"
        !          1066:                fi
        !          1067:                echo "${op_indent1}/* otherwise, we must do a slow indirect atomic ${op}: */ \\"
        !          1068:                echo "${op_else}" | tr '@' '\n'
        !          1069:                echo "${op_indent2}tme_memory${type}_${op}${size}(mem${op_x}${type_lock}, align_min)${op_semi} \\"
        !          1070:                ;;
        !          1071: 
        !          1072:            bus)
        !          1073:                echo "${op_indent0}/* if threads are cooperative, do a plain ${op}: */ \\"
        !          1074:                echo "${op_indent0}(TME_THREADS_COOPERATIVE) \\"
        !          1075:                echo "${op_then}"
        !          1076:                echo -n "${op_indent2}tme_memory_${op}${size}("
        !          1077:                # this strips off the tme_shared qualifier:
        !          1078:                #
        !          1079:                if test ${op} = read; then
        !          1080:                    echo -n "(_tme_const tme_uint${size}_t *) _tme_audit_type(mem, tme_uint${size}_t *)"
        !          1081:                else
        !          1082:                    echo -n "(tme_uint${size}_t *) _tme_cast_pointer_shared(tme_uint${size}_t *, tme_uint${size}_t *, mem)"
        !          1083:                fi
        !          1084:                echo "${op_x}, align_min)${op_semi} \\"
        !          1085: 
        !          1086:                echo "${op_indent1}/* otherwise, if we aren't locking for all memory accesses, the \\"
        !          1087:                echo "${op_indent1}   host supports misaligned ${size}-bit accesses, the host's bus \\"
        !          1088:                echo "${op_indent1}   boundary is greater than or equal to the emulated bus \\"
        !          1089:                echo "${op_indent1}   boundary, and this memory is aligned enough, do a single \\"
        !          1090:                echo "${op_indent1}   direct bus ${op}: */ \\"
        !          1091:                echo "${op_else_if}" | tr '@' '\n'
        !          1092:                echo "${op_indent1}(__tme_predict_true(TME_MEMORY_ALIGNMENT_ATOMIC(TME_MEMORY_TYPE_COMMON) != 0 \\"
        !          1093:                echo "${op_indent1}                    && _TME_ALIGNOF_INT${size}_T < sizeof(tme_uint${size}_t) \\"
        !          1094:                echo "${op_indent1}                    && TME_MEMORY_BUS_BOUNDARY >= (bus_boundary) \\"
        !          1095:                echo "${op_indent1}                    && _tme_memory_address_test(mem, _TME_ALIGNOF_INT${size}_T - 1, align_min) == 0)) \\"
        !          1096:                echo "${op_then}"
        !          1097:                echo "${op_indent2}(*_tme_audit_type(mem, tme_uint${size}_t *)) \\"
        !          1098:                if test ${op} = write; then
        !          1099:                    echo "${op_indent2}  = (x); \\"
        !          1100:                fi
        !          1101: 
        !          1102:                echo "${op_indent1}/* otherwise, if we're locking for all memory accesses, or \\"
        !          1103:                echo "${op_indent1}   if this memory must cross at least one host bus boundary \\"
        !          1104:                echo "${op_indent1}   and the host bus boundary is less than the emulated bus \\"
        !          1105:                echo "${op_indent1}   boundary, do a slow indirect atomic ${op}: */ \\"
        !          1106:                echo "${op_else_if}" | tr '@' '\n'
        !          1107:                echo "${op_indent1}(__tme_predict_false(TME_MEMORY_ALIGNMENT_ATOMIC(TME_MEMORY_TYPE_COMMON) == 0 \\"
        !          1108:                echo "${op_indent1}                     || (sizeof(tme_uint${size}_t) > TME_MEMORY_BUS_BOUNDARY \\"
        !          1109:                echo "${op_indent1}                         && TME_MEMORY_BUS_BOUNDARY < (bus_boundary)))) \\"
        !          1110:                echo "${op_then}"
        !          1111:                echo "${op_indent2}tme_memory_atomic_${op}${size}(mem${op_x}, lock, align_min)${op_semi} \\"
        !          1112: 
        !          1113:                echo "${op_indent1}/* otherwise, if the memory is not larger than the emulated \\"
        !          1114:                echo "${op_indent1}   bus boundary, or if size-alignment would mean an atomic \\"
        !          1115:                echo "${op_indent1}   host access and it is size-aligned, do a single atomic \\"
        !          1116:                echo "${op_indent1}   ${op}, which may be direct or slow: */ \\"
        !          1117:                echo "${op_else_if}" | tr '@' '\n'
        !          1118:                echo "${op_indent1}(__tme_predict_true((sizeof(tme_uint${size}_t) <= (bus_boundary) \\"
        !          1119:                echo "${op_indent1}                     || (TME_MEMORY_ALIGNMENT_ATOMIC(tme_uint${size}_t) != 0 \\"
        !          1120:                echo "${op_indent1}                         && TME_MEMORY_ALIGNMENT_ATOMIC(tme_uint${size}_t) <= sizeof(tme_uint${size}_t))) \\"
        !          1121:                echo "${op_indent1}                    && _tme_memory_address_test(mem, sizeof(tme_uint${size}_t) - 1, align_min) == 0)) \\"
        !          1122:                echo "${op_then}"
        !          1123:                echo "${op_indent2}tme_memory_atomic_${op}${size}(mem${op_x}, lock, sizeof(tme_uint${size}_t))${op_semi} \\"
        !          1124:                echo "${op_indent1}/* otherwise, we must do a slow bus ${op}: */ \\"
        !          1125:                echo "${op_else}" | tr '@' '\n'
        !          1126:                echo "${op_indent2}tme_memory${type}_${op}${size}(mem${op_x}${type_lock}, align_min, bus_boundary)${op_semi} \\"
        !          1127:                ;;
        !          1128: 
        !          1129:            esac
        !          1130: 
        !          1131:            # close this macro:
        !          1132:            #
        !          1133:            echo "${op_close}" | tr '@' '\n'
        !          1134:        done
        !          1135:     done
        !          1136: 
        !          1137:     echo ""
        !          1138:     echo "/* the ${size}-bit atomic operations: */"
        !          1139: 
        !          1140:     # the atomic operations.  NB that cx, read, and write are
        !          1141:     # deliberately at the end and in that order, to allow all earlier
        !          1142:     # default implementations to still use any host CPU-specific cx,
        !          1143:     # read and write macros:
        !          1144:     #
        !          1145:     for op in add sub mul div and or xor not neg xchg cx read write; do
        !          1146: 
        !          1147:        # dispatch on the operation.  NB that we don't need to
        !          1148:        # generate 8-bit atomic read and write operations:
        !          1149:        #
        !          1150:        op_rval="tme_uint${size}_t"
        !          1151:        op_const=
        !          1152:        op_proto_operand=", tme_uint${size}_t"
        !          1153:        op_operand=operand
        !          1154:        op_from=to
        !          1155:        op_operator=
        !          1156:        op_operation=
        !          1157:        op_indent=
        !          1158:        case ${op} in
        !          1159:        read)
        !          1160:            if test ${size} = 8; then continue; fi
        !          1161:            op_const="_tme_const "
        !          1162:            op_from=from
        !          1163:            op_proto_operand=
        !          1164:            ;;
        !          1165:        write)
        !          1166:            if test ${size} = 8; then continue; fi
        !          1167:            op_rval=void
        !          1168:            op_operand=value_written
        !          1169:            ;;
        !          1170:        cx)
        !          1171:            op_proto_operand=", tme_uint${size}_t, tme_uint${size}_t"
        !          1172:            op_operand=value_written
        !          1173:            op_indent="  "
        !          1174:            ;;
        !          1175:        add) op_operator='+' ;;
        !          1176:        sub) op_operator='-' ;;
        !          1177:        mul) op_operator='*' ;;
        !          1178:        div) op_operator='/' ;;
        !          1179:        and) op_operator='&' ;;
        !          1180:        or)  op_operator='|' ;;
        !          1181:        xor) op_operator='^' ;;
        !          1182:        not) op_operation='~value_read' ; op_proto_operand= ;;
        !          1183:        neg) op_operation='0 - value_read' ; op_proto_operand= ;;
        !          1184:        xchg) op_operand=value_written
        !          1185:        esac
        !          1186:        if test "x${op_operator}" != x; then
        !          1187:            op_operation="value_read ${op_operator} ${op_operand}"
        !          1188:        fi      
        !          1189: 
        !          1190:        # if we're making the header, just emit a prototype:
        !          1191:        #
        !          1192:        if $header; then
        !          1193:            echo "${op_rval} tme_memory_atomic_${op}${size} _TME_P((${op_const}tme_shared tme_uint${size}_t *${op_proto_operand}, tme_rwlock_t *, unsigned int));"
        !          1194:            continue
        !          1195:        fi
        !          1196: 
        !          1197:        echo ""
        !          1198:        echo "/* undefine any macro version of tme_memory_atomic_${op}${size}: */"
        !          1199:        echo "#undef tme_memory_atomic_${op}${size}"
        !          1200:        echo ""
        !          1201:        echo "/* the ${size}-bit atomic ${op} function: */"
        !          1202:        echo "${op_rval}"
        !          1203:        echo "tme_memory_atomic_${op}${size}(${op_const}tme_shared tme_uint${size}_t *memory,"
        !          1204:        if test ${op} = cx; then
        !          1205:            echo "                        tme_uint${size}_t value_cmp,"
        !          1206:        fi
        !          1207:        if test "x${op_proto_operand}" != x; then
        !          1208:            echo "                        tme_uint${size}_t ${op_operand},"
        !          1209:        fi
        !          1210:        echo "                        tme_rwlock_t *rwlock,"
        !          1211:        echo "                        unsigned int align_min)"
        !          1212:        echo "{"
        !          1213:        if test ${op} != write; then
        !          1214:            echo "  tme_uint${size}_t value_read;"
        !          1215:        fi
        !          1216:        if test "x${op_operation}" != x; then
        !          1217:            echo "  tme_uint${size}_t value_written;"
        !          1218:        fi
        !          1219:        if test ${op} = read || test ${op} = write || test ${op} = cx; then :; else
        !          1220:            echo "  tme_uint${size}_t value_read_verify;"
        !          1221:        fi
        !          1222:        echo ""
        !          1223:        echo "  /* if we can't make direct accesses at all, all atomic"
        !          1224:        echo "     accesses must be done under lock.  (when threads are"
        !          1225:        echo "     cooperative the actual locking isn't needed): */"
        !          1226:        echo "  if (TME_MEMORY_ALIGNMENT_ATOMIC(TME_MEMORY_TYPE_COMMON) == 0) {"
        !          1227:        echo "    if (!TME_THREADS_COOPERATIVE) {"
        !          1228:        if test ${op} = read; then
        !          1229:            echo "      tme_rwlock_rdlock(rwlock);"
        !          1230:        else
        !          1231:            echo "      tme_rwlock_wrlock(rwlock);"
        !          1232:        fi
        !          1233:        echo "    }"
        !          1234:        if test ${op} != write; then
        !          1235:            echo "    value_read = tme_memory_read${size}((_tme_const tme_uint${size}_t *) memory, align_min);"
        !          1236:        fi
        !          1237:        if test ${op} = cx; then
        !          1238:            echo "    if (value_read == value_cmp) {"
        !          1239:        fi
        !          1240:        if test "x${op_operation}" != x; then
        !          1241:            echo "    value_written = ${op_operation};"
        !          1242:        fi
        !          1243:        if test ${op} != read; then
        !          1244:            echo "${op_indent}    tme_memory_write${size}((tme_uint${size}_t *) memory, value_written, align_min);"
        !          1245:        fi
        !          1246:        if test "x${op_indent}" != x; then
        !          1247:            echo "    }"
        !          1248:        fi
        !          1249:        echo "    if (!TME_THREADS_COOPERATIVE) {"
        !          1250:        echo "      tme_rwlock_unlock(rwlock);"
        !          1251:        echo "    }"
        !          1252:        echo "  }"
        !          1253:        echo ""
        !          1254:        echo "  /* otherwise, threads are not cooperative and this host CPU"
        !          1255:        echo "     can make atomic accesses to at least the most common memory"
        !          1256:        echo "     size."
        !          1257:        echo ""
        !          1258:        echo "     in that case, the only reason this function should get"
        !          1259:        echo "     called is if the host CPU can't do an atomic ${size}-bit"
        !          1260:        echo "     ${op} at all, or if it can't do it at this alignment."
        !          1261:        if test ${op} = read || test ${op} = write || test ${op} = cx; then
        !          1262:            echo ""
        !          1263:            echo "     we assume that these problematic atomic ${op}s are rare,"
        !          1264:            echo "     and to emulate them we simply stop all other threads while"
        !          1265:            echo "     doing the ${op}: */"
        !          1266:            echo "  else {"
        !          1267:            echo "    tme_thread_suspend_others();"
        !          1268:            if test ${op} != write; then
        !          1269:                echo "    value_read = tme_memory_read${size}((_tme_const tme_uint${size}_t *) memory, align_min);"
        !          1270:            fi
        !          1271:            if test ${op} = cx; then
        !          1272:                echo "    if (value_read == value_cmp) {"
        !          1273:            fi
        !          1274:            if test ${op} != read; then
        !          1275:                echo "${op_indent}    tme_memory_write${size}((tme_uint${size}_t *) memory, value_written, align_min);"
        !          1276:            fi
        !          1277:            if test "x${op_indent}" != x; then
        !          1278:                echo "    }"
        !          1279:            fi
        !          1280:            echo "    tme_thread_resume_others();"
        !          1281:            echo "  }"
        !          1282:        else
        !          1283:            echo ""
        !          1284:            echo "     we emulate the atomic ${size}-bit ${op} with a compare-and-exchange: */"
        !          1285:            echo "  else {"
        !          1286:            echo ""
        !          1287:            echo "    /* do an atomic read of the memory: */"
        !          1288:            echo "    value_read = tme_memory_atomic_read${size}(memory, rwlock, align_min);"
        !          1289:            echo ""
        !          1290:            echo "    /* spin the ${op} in a compare-and-exchange loop: */"
        !          1291:            echo "    for (;;) {"
        !          1292:            if test "x${op_operation}" != x; then
        !          1293:                echo ""
        !          1294:                echo "      /* make the value to write: */"
        !          1295:                echo "      value_written = ${op_operation};"
        !          1296:            fi
        !          1297:            echo ""
        !          1298:            echo "      /* try the compare-and-exchange: */"
        !          1299:            echo "      value_read_verify = tme_memory_atomic_cx${size}(memory, value_read, value_written, rwlock, align_min);"
        !          1300:            echo ""
        !          1301:            echo "      /* if the compare-and-exchange failed: */"
        !          1302:            echo "      if (__tme_predict_false(value_read_verify != value_read)) {"
        !          1303:            echo ""
        !          1304:            echo "        /* loop with the new value read from the memory: */"
        !          1305:            echo "        value_read = value_read_verify;"
        !          1306:            echo "        continue;"
        !          1307:            echo "      }"
        !          1308:            echo ""
        !          1309:            echo "      /* stop now: */"
        !          1310:            echo "      break;"
        !          1311:            echo "    }"
        !          1312:            echo "  }"
        !          1313:        fi
        !          1314:        if test ${op} != write; then
        !          1315:            echo ""
        !          1316:            echo "  /* return the value read: */"
        !          1317:            echo "  return (value_read);"
        !          1318:        fi
        !          1319:        echo "}"
        !          1320:     done
        !          1321: 
        !          1322:     if test `expr ${size} \>= ${size_ifdef}` = 1; then
        !          1323:        echo ""
        !          1324:        echo "#endif /* TME_HAVE_INT${size}_T */"
        !          1325:     fi
        !          1326: 
        !          1327: done
        !          1328: 
        !          1329: # done:
        !          1330: #
        !          1331: exit 0         

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.