Annotation of uae/src/execlib.c, revision 1.1.1.2

1.1       root        1:  /*
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   *
                      4:   * exec.library emulation
                      5:   *
                      6:   * Copyright 1996 Bernd Schmidt
                      7:   */
                      8: 
                      9: #include "sysconfig.h"
                     10: #include "sysdeps.h"
                     11: 
                     12: #include <assert.h>
                     13: #include <signal.h>
1.1.1.2 ! root       14: #include <ctype.h>
1.1       root       15: 
                     16: #include "config.h"
                     17: #include "options.h"
1.1.1.2 ! root       18: #include "machdep/exectasks.h"
        !            19: #include "machdep/m68k.h"
1.1       root       20: #include "memory.h"
                     21: #include "custom.h"
1.1.1.2 ! root       22: #include "readcpu.h"
1.1       root       23: #include "newcpu.h"
                     24: #include "xwin.h"
                     25: #include "autoconf.h"
                     26: #include "osemu.h"
1.1.1.2 ! root       27: #include "execlib.h"
1.1       root       28: 
1.1.1.2 ! root       29: #ifdef USE_EXECLIB
        !            30: 
        !            31: CPTR EXEC_sysbase;
1.1       root       32: 
                     33: /*
                     34:  * Exec list management
                     35:  */
                     36: 
                     37: void EXEC_NewList(CPTR list)
                     38: {
                     39:     put_long(list, list + 4);
                     40:     put_long(list + 4, 0);
                     41:     put_long(list + 8, list);
                     42: }
                     43: 
                     44: void EXEC_Insert(CPTR list, CPTR node, CPTR pred)
                     45: {
                     46:     CPTR succ;
                     47:     if (pred == 0)
                     48:        pred = list;
                     49:     put_long(node, succ = get_long(pred));
                     50:     put_long(pred, node);
                     51:     put_long(succ + 4, node);
                     52:     put_long(node + 4, pred);
                     53: }
                     54: 
                     55: void EXEC_Enqueue(CPTR list, CPTR node)
                     56: {
                     57:     int pri = (BYTE)get_byte (node + 9);
                     58:     CPTR lnode = get_long(list); /* lh_Head */
                     59:     CPTR prev = 0, next;
                     60:     
                     61:     for (;(next = get_long(lnode)) != 0 && (BYTE)get_byte(lnode + 9) >= pri;) {
                     62:        prev = lnode;
                     63:        lnode = next;
                     64:     }
                     65:     EXEC_Insert(list, node, prev);
                     66: }
                     67: 
                     68: void EXEC_Remove(CPTR node)
                     69: {
                     70:     CPTR pred = get_long(node + 4), succ = get_long(node);
                     71:     put_long(pred, succ);
                     72:     put_long(succ + 4, pred);
                     73: }
                     74: 
                     75: ULONG EXEC_RemHead(CPTR list)
                     76: {
                     77:     CPTR head = get_long(list);
                     78:     if (get_long(head) == 0)
                     79:        return 0;
                     80:     EXEC_Remove(head);
                     81:     return head;
                     82: }
                     83: 
                     84: ULONG EXEC_RemTail(CPTR list)
                     85: {
                     86:     CPTR tail = get_long(list + 8);
                     87:     if (get_long(tail + 4) == 0)
                     88:        return 0;
                     89:     
                     90:     EXEC_Remove(tail);
                     91:     return tail;
                     92: }
                     93: 
                     94: void EXEC_AddTail(CPTR list, CPTR node) 
                     95: {
                     96:     EXEC_Insert(list, node, get_long(list + 8)); 
                     97: }
                     98: 
                     99: CPTR EXEC_FindName(CPTR start, char *name)
                    100: {
1.1.1.2 ! root      101:     CPTR node, next;
        !           102: 
1.1       root      103:     if (name == NULL)
                    104:        return 0;
                    105:     
1.1.1.2 ! root      106:     for (node = get_long(start);(next = get_long(node)) != 0; node = next) {
1.1       root      107:        CPTR nnp;
                    108:        char *nn;
                    109: 
                    110:        nnp = get_long(node + 10);
1.1.1.2 ! root      111:        if (nnp != 0 && (nn = raddr(nnp)) != NULL)
1.1       root      112:            if (strcmp(nn, name) == 0)
                    113:                return node;
                    114:        start = node;
                    115:     }
                    116:     return 0;
                    117: }
                    118: 
1.1.1.2 ! root      119: static ULONG execl_Enqueue(void) { EXEC_Enqueue(m68k_areg(regs, 0), m68k_areg(regs, 1)); return 0; }
        !           120: static ULONG execl_Insert(void) { EXEC_Insert(m68k_areg(regs, 0), m68k_areg(regs, 1), m68k_areg(regs, 2)); return 0; }
        !           121: static ULONG execl_AddHead(void) { EXEC_Insert(m68k_areg(regs, 0), m68k_areg(regs, 1), 0); return 0; }
        !           122: static ULONG execl_AddTail(void) { EXEC_Insert(m68k_areg(regs, 0), m68k_areg(regs, 1), get_long(m68k_areg(regs, 0) + 8)); return 0; }
        !           123: static ULONG execl_Remove(void) { EXEC_Remove(m68k_areg(regs, 1)); return 0; }
        !           124: static ULONG execl_RemHead(void) { return EXEC_RemHead(m68k_areg(regs, 0)); }
        !           125: static ULONG execl_RemTail(void) { return EXEC_RemTail(m68k_areg(regs, 0)); }
        !           126: static ULONG execl_FindName(void) { CPTR n = EXEC_FindName(m68k_areg(regs, 0), raddr(m68k_areg(regs, 1))); ZFLG = n == 0; return n; }
1.1       root      127: 
                    128: /*
                    129:  * Miscellaneous
                    130:  */
                    131: 
                    132: void EXEC_InitStruct(CPTR inittable, CPTR memory, unsigned long size)
                    133: {
                    134:     CPTR dptr = memory;
1.1.1.2 ! root      135:     UBYTE *mem = (UBYTE *)raddr(memory);
1.1       root      136:     if (memory == 0 || mem == NULL || !valid_address(memory, size)) {
                    137:        fprintf(stderr, "Foo\n");
                    138:        return;
                    139:     }
                    140:     memset(mem, 0, size);
                    141:     fprintf(stderr, "InitStruct\n");
                    142:     for (;;) {
                    143:        UBYTE command;
                    144:        int count, desttype, srcloc;
                    145:        ULONG offset;
                    146: 
                    147:        /* Read commands from even bytes */
                    148:        inittable = (inittable + 1) & ~1;
                    149: 
                    150:        command = get_byte(inittable);
                    151:        if (command == 0)
                    152:            break;
                    153:        desttype = (command >> 6) & 3;
                    154:        srcloc = (command >> 4) & 3;
                    155:        count = (command & 15) + 1;
                    156: 
                    157:        if (desttype == 3) {
                    158:            dptr = memory + (get_long(inittable) & 0xFFFFFF);
                    159:            inittable += 4;
                    160:        } else if (desttype == 2) {
                    161:            dptr = memory + get_byte(inittable+1), inittable += 2;
                    162:        } else 
                    163:            inittable++;
                    164: 
                    165:        if (srcloc != 0)
                    166:            inittable = (inittable + 1) & ~1;
                    167: 
                    168:        if (desttype != 1) {
                    169:            for(; count > 0; count--) {
                    170:                switch (srcloc) {
                    171:                 case 0: put_long(dptr, get_long(inittable)); dptr += 4; inittable += 4; break;
                    172:                 case 1: put_word(dptr, get_word(inittable)); dptr += 2; inittable += 2; break;
                    173:                 case 2: put_byte(dptr, get_byte(inittable)); dptr += 1; inittable += 1; break;
                    174:                }
                    175:            }
                    176:        } else {
                    177:            ULONG data;
                    178:            switch (srcloc) {
                    179:             case 0: data = get_byte(inittable); inittable += 1; break;
                    180:             case 1: data = get_word(inittable); inittable += 2; break;
                    181:             case 2: data = get_long(inittable); inittable += 4; break;
                    182:             default: data = 0; /* Alert */ break;
                    183:            }
                    184:            for(; count > 0; count--) {
                    185:                switch (srcloc) {
                    186:                 case 0: put_long(dptr, data); dptr += 4; break;
                    187:                 case 1: put_word(dptr, data); dptr += 2; break;
                    188:                 case 2: put_byte(dptr, data); dptr += 1; break;
                    189:                }
                    190:            }
                    191:        }
                    192:     }
                    193: }
                    194: /* The size parameter sometimes seems to contain garbage in the top 16 bit */
1.1.1.2 ! root      195: static ULONG execl_InitStruct(void) { EXEC_InitStruct(m68k_areg(regs, 1), m68k_areg(regs, 2), m68k_dreg(regs, 0) & 0xFFFF); return 0; }
        !           196: 
        !           197: static ULONG execl_GetCC(void)
        !           198: {
        !           199:     MakeSR();
        !           200:     m68k_dreg(regs, 0) = regs.sr & 0xFF;
        !           201:     return 0; /* ignored */
        !           202: }
1.1       root      203: 
                    204: /*
                    205:  * Interrupts
                    206:  * This is all very confusing. As I see things, the IntVects field of the
                    207:  * ExecBase is set up as follows:
                    208:  *   One interrupt may either be assigned an IntServer, or an IntHandler.
                    209:  *   PORTS, COPER, VERTB EXTER and NMI are set up as Servers (at least that's
                    210:  *   what the AutoDocs say), the others as IntHandlers.
                    211:  *   An IntServer field has a pointer to an Exec list in the iv_Data field,
                    212:  *   the list contains all the server Interrupt nodes in a nice chain. The
                    213:  *   iv_Node field is zero. For an IntHandler, the iv_Node field contains a
                    214:  *   pointer to the node that was passed in SetIntVector.
                    215:  */
                    216: 
                    217: CPTR EXEC_SetIntVector(int number, CPTR interrupt)
                    218: {
1.1.1.2 ! root      219:     CPTR oldvec = get_long(EXEC_sysbase + 84 + 12*number + 8);
1.1       root      220:     if (interrupt == 0) {
1.1.1.2 ! root      221:        put_long(EXEC_sysbase + 84 + 12*number, 0);
        !           222:        put_long(EXEC_sysbase + 84 + 12*number + 4, 0);
        !           223:        put_long(EXEC_sysbase + 84 + 12*number + 8, 0);
1.1       root      224:     } else {
1.1.1.2 ! root      225:        put_long(EXEC_sysbase + 84 + 12*number, get_long(interrupt + 14));
        !           226:        put_long(EXEC_sysbase + 84 + 12*number + 4, get_long(interrupt + 18));
        !           227:        put_long(EXEC_sysbase + 84 + 12*number + 8, interrupt);
1.1       root      228:     }
                    229:     return oldvec;
                    230: }
                    231: 
                    232: void EXEC_RemIntServer(ULONG nr, CPTR interrupt)
                    233: {
1.1.1.2 ! root      234:     CPTR list = get_long(EXEC_sysbase + 84 + nr*12);
1.1       root      235:     
                    236:     EXEC_Remove(interrupt);
                    237:     /* Disable interrupt if necessary */
                    238:     if (get_long(get_long(list)) == 0)
                    239:        put_word(0xDFF09A, 1 << nr);
                    240: }
                    241: 
                    242: void EXEC_AddIntServer(ULONG nr, CPTR interrupt)
                    243: {
1.1.1.2 ! root      244:     CPTR list = get_long(EXEC_sysbase + 84 + nr*12);
1.1       root      245:     int was_empty;
                    246: 
                    247:     /* Disable interrupt if necessary */
                    248:     was_empty = get_long(get_long(list)) == 0;
                    249:     
                    250:     EXEC_Enqueue(list, interrupt);
                    251:     if (was_empty)
                    252:        put_word(0xDFF09A, 0x8000 | (1 << nr));
                    253:     
                    254: }
                    255: 
1.1.1.2 ! root      256: static ULONG execl_SetIntVector(void) { return EXEC_SetIntVector(m68k_dreg(regs, 0), m68k_areg(regs, 1)); }
        !           257: static ULONG execl_AddIntServer(void) { EXEC_AddIntServer(m68k_dreg(regs, 0) & 15, m68k_areg(regs, 1)); return 0; }
        !           258: static ULONG execl_RemIntServer(void) { EXEC_RemIntServer(m68k_dreg(regs, 0) & 15, m68k_areg(regs, 1)); return 0; }
1.1       root      259: 
                    260: /*
                    261:  * Memory functions
                    262:  */
                    263: 
                    264: #define MEMF_PUBLIC 1
                    265: #define MEMF_CHIP 2
                    266: #define MEMF_FAST 4
                    267: #define MEMF_LOCAL 256
                    268: #define MEMF_24BITDMA 512
                    269: #define MEMF_CLEAR (1<<16)
                    270: #define MEMF_LARGEST (1<<17)
                    271: #define MEMF_REVERSE (1<<18)
                    272: #define MEMF_TOTAL (1<<19)
                    273: 
                    274: CPTR EXEC_Allocate(CPTR memheader, unsigned long size)
                    275: {
                    276:     CPTR chunk, chunkpp;
                    277:     unsigned long avail;
                    278:     
                    279:     size = (size + 7) & ~7;
                    280:     
                    281:     if (size == 0 || size > get_long(memheader + 28))
                    282:        return 0;
                    283:        
                    284:     for (chunk = get_long(chunkpp = memheader + 16); chunk != 0; chunkpp = chunk, chunk = get_long(chunk))
                    285:        if ((avail = get_long(chunk + 4)) >= size) {
                    286:            CPTR nextchunk = get_long(chunk);
                    287:            if (avail-size == 0)
                    288:                put_long(chunkpp, nextchunk);
                    289:            else {
                    290:                put_long(chunkpp, chunk + size);
                    291:                put_long(chunk + size, nextchunk);
                    292:                put_long(chunk + size + 4, avail - size);
                    293:            }
                    294:            put_long(memheader + 28, get_long(memheader + 28) - size);
                    295:            return chunk;
                    296:        }
                    297:     return 0;
                    298: }
                    299: 
                    300: void EXEC_Deallocate(CPTR memheader, CPTR addr, unsigned long size)
                    301: {
                    302:     CPTR chunk, chunkpp;
                    303:     CPTR areaend;
                    304: 
                    305:     if (addr == 0)
                    306:        return;
                    307: 
                    308:     size = (size + 7) & ~7;
                    309:     areaend = addr + size;
                    310:     
                    311:     put_long(memheader + 28, get_long(memheader + 28) + size);
                    312:     
                    313:     for (chunk = get_long(chunkpp = memheader + 16); chunk != 0; chunkpp = chunk, chunk = get_long(chunk)) {
                    314:        if (chunk + get_long(chunk + 4) == addr) {
                    315:            /* Merge with this and go ahead so we can also merge with the next */
                    316:            put_long(chunkpp, get_long(chunk));
                    317:            addr = chunk; size += get_long(chunk + 4);
                    318:            chunk = chunkpp;
                    319:            continue;
                    320:        }
                    321:        if (areaend == chunk) {
                    322:            /* Merge with previous */
                    323:            put_long(chunkpp, addr);
                    324:            put_long(addr, get_long(chunk));
                    325:            put_long(addr + 4, get_long(chunk + 4) + size);
                    326:            return;
                    327:        }
                    328:        if (chunk > addr)
                    329:            break;
                    330:     }
                    331:     put_long(chunkpp, addr);
                    332:     put_long(addr, chunk);
                    333:     put_long(addr + 4, size);
                    334: }
                    335: 
                    336: CPTR EXEC_AllocMem(unsigned long size, ULONG requirements)
                    337: {
1.1.1.2 ! root      338:     CPTR nextmh,  memheader = get_long(EXEC_sysbase + 322);
1.1       root      339:     ULONG attrs = requirements & (MEMF_PUBLIC | MEMF_CHIP | MEMF_FAST);
                    340:     CPTR result = 0;
                    341: 
                    342:     size = (size + 7) & ~7;
                    343: 
                    344:     for (;(nextmh = get_long(memheader)) != 0; memheader = nextmh) {
                    345:        if ((get_word(memheader + 14) & attrs) != attrs)
                    346:            continue;
                    347:        result = EXEC_Allocate(memheader, size);
                    348:        if (result != 0)
                    349:            break;
                    350:     }
                    351:     if (result) {
                    352:        if (requirements & MEMF_CLEAR)
1.1.1.2 ! root      353:            memset(raddr(result), 0, size);
1.1       root      354:     }
                    355:     return result;
                    356: }
                    357: 
                    358: CPTR EXEC_AllocEntry(CPTR ml)
                    359: {
                    360:     CPTR newml = EXEC_AllocMem(16 + 8*get_word(ml + 14), MEMF_PUBLIC|MEMF_CLEAR);
                    361:     int i;
                    362: 
                    363:     if (newml == 0)
                    364:        return 0x80000000|MEMF_PUBLIC;
                    365:     for (i = 0; i < get_word(ml + 14); i++) {
                    366:        ULONG reqs = get_long(ml + 16 + 8*i);
                    367:        ULONG addr = EXEC_AllocMem(get_long(ml + 16 + 8*i + 4), reqs);
                    368:        if (addr == 0)
                    369:            /* Thank god for SetPatch */
                    370:            return 0x80000000 | reqs;
                    371:        put_long(newml + 16 + 8*i, addr);
                    372:        put_long(newml + 16 + 8*i + 4, reqs);
                    373:     }
                    374:     return newml;
                    375: }
                    376: 
                    377: void EXEC_FreeMem(CPTR addr, unsigned long size)
                    378: {
1.1.1.2 ! root      379:     CPTR nextmh,  memheader = get_long(EXEC_sysbase + 322);
1.1       root      380: 
                    381:     size = (size + 7) & ~7;
                    382:     if (addr == 0)
                    383:        return;
1.1.1.2 ! root      384:     if (size == 0) {
        !           385:        fprintf(stderr, "warning: Freemem(..., 0)\n");
        !           386:        return;
        !           387:     }
1.1       root      388: 
                    389:     for (;(nextmh = get_long(memheader)) != 0; memheader = nextmh) {
                    390:        if (get_long(memheader + 20) <= addr
                    391:            && get_long(memheader + 24) > addr) {
                    392:            EXEC_Deallocate(memheader, addr, size);
                    393:            return;
                    394:        }
                    395:     }
                    396: }
                    397: 
                    398: unsigned long EXEC_AvailMem(ULONG requirements)
                    399: {
                    400:     ULONG attrs = requirements & (MEMF_PUBLIC | MEMF_CHIP | MEMF_FAST);
1.1.1.2 ! root      401:     CPTR nextmh, memheader = get_long(EXEC_sysbase + 322);
1.1       root      402:     CPTR result = 0;
                    403: 
                    404:     for (;(nextmh = get_long(memheader)) != 0; memheader = nextmh) {
                    405:        if ((get_word(memheader + 14) & attrs) != attrs)
                    406:            continue;
                    407:        if (attrs & MEMF_LARGEST) {
                    408:            unsigned long maxsize = 0;
                    409:            CPTR chunk;
                    410:            for (chunk = get_long(memheader + 16); chunk != 0; chunk = get_long(chunk))
                    411:                if (get_long(chunk+4) > maxsize)
                    412:                    maxsize = get_long(chunk + 4);
                    413:            result += maxsize;
                    414:        } else if (attrs & MEMF_TOTAL) {
                    415:            result += get_long(memheader + 24) - get_long(memheader + 20);
                    416:        } else result += get_long(memheader + 28);
                    417:     }
                    418:     return result;
                    419: }
                    420: 
                    421: void EXEC_AddMemList(unsigned long size, ULONG attrs, int pri, CPTR base,
                    422:                     CPTR name)
                    423: {
1.1.1.2 ! root      424:     if (size == 0xFFFFFFFF) {
        !           425:        fprintf(stderr, "Weird AddMemList call\n");
        !           426:        return;
        !           427:     }
        !           428:        
1.1       root      429:     put_byte(base + 8, 0);
                    430:     put_byte(base + 9, pri);
                    431:     put_long(base + 10, name);
                    432:     put_word(base + 14, attrs);
                    433:     put_long(base + 16, base + 32);
                    434:     put_long(base + 20, base + 32);
                    435:     put_long(base + 36, size - 32);
                    436:     put_long(base + 28, size - 32);
                    437:     put_long(base + 24, base + size);
1.1.1.2 ! root      438:     EXEC_Enqueue(EXEC_sysbase + 322, base);
1.1       root      439: }
                    440: 
                    441: static ULONG execl_AddMemList(void)
                    442: {
1.1.1.2 ! root      443:     EXEC_AddMemList(m68k_dreg(regs, 0), m68k_dreg(regs, 1), (LONG)m68k_dreg(regs, 2), m68k_areg(regs, 0), m68k_areg(regs, 1));
1.1       root      444:     return 0;
                    445: }
                    446: 
                    447: static ULONG execl_CopyMem(void)
                    448: {
1.1.1.2 ! root      449:     UBYTE *src = (UBYTE *)raddr(m68k_areg(regs, 0));
        !           450:     UBYTE *dst = (UBYTE *)raddr(m68k_areg(regs, 1));
1.1       root      451: 
                    452:     if (src != NULL && dst != NULL
1.1.1.2 ! root      453:        && valid_address(m68k_areg(regs, 0), m68k_dreg(regs, 0))
        !           454:        && valid_address(m68k_areg(regs, 1), m68k_dreg(regs, 0)))
        !           455:        memcpy(dst, src, m68k_dreg(regs, 0));
        !           456:     else {
        !           457:        /* Ho hum. This happens when copying expansion card data. We
        !           458:         * better do something sensible in this case */
        !           459:        unsigned long int i;
        !           460:        for(i = 0; i < m68k_dreg(regs, 0); i++)
        !           461:            put_byte(m68k_areg(regs, 1) + i, get_byte(m68k_areg(regs, 0) + i));
        !           462:     }
1.1       root      463:     return 0;
                    464: }
                    465: 
1.1.1.2 ! root      466: static ULONG execl_AllocMem(void) { return EXEC_AllocMem(m68k_dreg(regs, 0), m68k_dreg(regs, 1)); }
        !           467: static ULONG execl_AllocEntry(void) { return EXEC_AllocEntry(m68k_areg(regs, 0)); }
        !           468: static ULONG execl_Allocate(void) { return EXEC_Allocate(m68k_areg(regs, 0), m68k_dreg(regs, 0)); }
        !           469: static ULONG execl_FreeMem(void) { EXEC_FreeMem(m68k_areg(regs, 1), m68k_dreg(regs, 0)); return 0; }
        !           470: static ULONG execl_AvailMem(void) { return EXEC_AvailMem(m68k_dreg(regs, 1)); }
        !           471: static ULONG execl_Deallocate(void) { EXEC_Deallocate(m68k_areg(regs, 0), m68k_areg(regs, 1), m68k_dreg(regs, 0)); return 0; }
1.1       root      472: 
                    473: /*
                    474:  * Scheduling
                    475:  */
                    476: 
                    477: #define TS_RUN 2
                    478: #define TS_READY 3
                    479: #define TS_WAIT 4
                    480: #define TS_EXCEPT 5
1.1.1.2 ! root      481: #define TS_REMOVED 6
1.1       root      482: 
                    483: struct NewTask {
                    484:     struct NewTask *next, *prev;
                    485:     CPTR exectask;
1.1.1.2 ! root      486:     struct switch_struct sws;
1.1       root      487:     void *stack;
                    488:     struct regstruct regs;
                    489:     struct flag_struct flags;
                    490: };
                    491: 
                    492: static struct NewTask idle_task;
1.1.1.2 ! root      493: static int intr_count, need_resched, quantum_elapsed;
        !           494: static struct NewTask *task_to_kill;
1.1       root      495: 
                    496: static struct NewTask *find_newtask(CPTR task)
                    497: {
                    498:     /* Ugh, this is ugly */
                    499:     struct NewTask *t = &idle_task;
                    500:     do {
                    501:        if (t->exectask == task)
                    502:            return t;
                    503:        t = t->next;
                    504:     } while (t != &idle_task);
                    505:     fprintf(stderr, "Uh oh. Task list corrupt\n");
1.1.1.2 ! root      506:     return 0;
1.1       root      507: }
                    508: 
1.1.1.2 ! root      509: void EXEC_QuantumElapsed(void)
        !           510: {
        !           511:     need_resched = 1;
        !           512:     quantum_elapsed = 1;
        !           513: }
        !           514: 
        !           515: static int trace_schedules = 0;
        !           516: 
1.1       root      517: static void schedule(void)
                    518: {
1.1.1.2 ! root      519:     CPTR readylist = EXEC_sysbase + 406;
1.1       root      520:     CPTR readytask = get_long(readylist);
1.1.1.2 ! root      521:     CPTR runtask = get_long(EXEC_sysbase + 276);
1.1       root      522:     struct NewTask *runtask_nt, *readytask_nt;
                    523:     unsigned long oldflags;
1.1.1.2 ! root      524:     UBYTE oldstate;
1.1       root      525:     int idis;
                    526:     
1.1.1.2 ! root      527:     TIMER_block();
        !           528:     
1.1       root      529:     need_resched = 0;
                    530:     /* Any ready tasks? */
                    531:     if (get_long(readytask) == 0)
1.1.1.2 ! root      532:        goto dont_schedule;
1.1       root      533:     
1.1.1.2 ! root      534:     /* If the running task is going to sleep, don't check priorities */
        !           535:     oldstate = get_byte(runtask + 15);
        !           536:     if (oldstate != TS_WAIT && oldstate != TS_REMOVED) {
1.1       root      537:        /* Has the running task a higher priority than any ready tasks? */
                    538:        if ((BYTE)get_byte(runtask + 9) > (BYTE)get_byte(readytask + 9))
1.1.1.2 ! root      539:            goto dont_schedule;
        !           540:        if ((BYTE)get_byte(runtask + 9) == (BYTE)get_byte(readytask + 9)
        !           541:            && !quantum_elapsed)
        !           542:            goto dont_schedule;
        !           543:        quantum_elapsed = 0;
        !           544:     }
        !           545:     if (oldstate == TS_RUN)
        !           546:        put_byte(runtask + 15, oldstate = TS_READY);
        !           547:     if (oldstate == TS_WAIT)
        !           548:        EXEC_Enqueue(EXEC_sysbase + 420, runtask);
        !           549:     else 
        !           550:        /* Removed tasks end up here also, so we can safely Remove() them
        !           551:         * always. */
1.1       root      552:        EXEC_Enqueue(readylist, runtask);
                    553:     put_byte(readytask + 15, TS_RUN);
                    554:     EXEC_Remove(readytask);
                    555:     
                    556:     readytask_nt = find_newtask(readytask);
                    557:     runtask_nt = find_newtask(runtask);
                    558: 
                    559:     oldflags = regs.spcflags;
                    560:     runtask_nt->regs = regs;
                    561:     runtask_nt->flags = regflags;
                    562:     regs = readytask_nt->regs;
                    563:     regflags = readytask_nt->flags;
                    564:     regs.spcflags = (regs.spcflags & ~PRESERVED_FLAGS) | (oldflags & PRESERVED_FLAGS);
1.1.1.2 ! root      565:     regs.isp = runtask_nt->regs.isp;
        !           566:     regs.msp = runtask_nt->regs.msp;
        !           567:     put_byte(runtask + 16, get_byte(EXEC_sysbase + 294));
        !           568:     put_byte(runtask + 17, get_byte(EXEC_sysbase + 295));
        !           569:     put_byte(EXEC_sysbase + 294, idis = get_byte(readytask + 16));
        !           570:     put_byte(EXEC_sysbase + 295, get_byte(readytask + 17));
        !           571:     put_long(EXEC_sysbase + 276, readytask);
1.1       root      572:     /* Set INTENA according to new interrupt enable status */
                    573:     if (idis == 0xFF)
                    574:        put_word(0xDFF09A, 0xC000);
                    575:     else
                    576:        put_word(0xDFF09A, 0x4000);
1.1.1.2 ! root      577: 
        !           578:     if (trace_schedules)
        !           579:        fprintf(stderr, "Task switch: new task %s\n", raddr(get_long(readytask + 10)));
        !           580: 
        !           581:     EXEC_SWITCH_TASKS(runtask_nt, readytask_nt);
        !           582: 
1.1       root      583:     regs.spcflags &= ~SPCFLAG_BRK;
1.1.1.2 ! root      584:     
        !           585:     dont_schedule:
        !           586:     
        !           587:     TIMER_unblock();
        !           588: 
        !           589:     /* Now we know we are running in a live task, so we can safely remove
        !           590:      * a corpse if necessary */
        !           591:     if (task_to_kill != NULL) {
        !           592:        struct NewTask *nt = task_to_kill;
        !           593:        task_to_kill = NULL;
        !           594:        EXEC_Remove(nt->exectask);
        !           595:        EXEC_FreeMem(nt->exectask, 92);
        !           596:        free(nt->stack);
        !           597:        nt->prev->next = nt->next;
        !           598:        nt->next->prev = nt->prev;
        !           599:        free(nt);
        !           600:     }
1.1       root      601: }
                    602: 
                    603: static __inline__ void maybe_schedule(void)
                    604: {
                    605:     /* @@@ Should we avoid a schedule when supervisor bit is set?
                    606:      * Definitely not if the running task is the idle task */
1.1.1.2 ! root      607:     if (intr_count == 0 && get_byte(EXEC_sysbase + 294) == 0xFF && get_byte(EXEC_sysbase + 295) == 0xFF && need_resched)
1.1       root      608:        schedule();
                    609: }
                    610: 
                    611: /*
                    612:  * Signals
                    613:  */
                    614: 
                    615: int EXEC_AllocSignal(int signum)
                    616: {
1.1.1.2 ! root      617:     CPTR thistask = get_long(EXEC_sysbase + 276);
1.1       root      618:     ULONG sigalloc = get_long(thistask + 18);
                    619:     if (signum == -1)
                    620:        for (signum = 0; signum < 32; signum++)
                    621:            if ((sigalloc & (1 << signum)) == 0)
                    622:                break;
                    623:     
                    624:     if ((sigalloc & (1 << signum)) == 0) {
                    625:        put_long(thistask + 18, sigalloc | (1 << signum));
                    626:     } else
                    627:        signum = -1;
                    628: 
                    629:     return signum;
                    630: }
                    631: 
                    632: void EXEC_FreeSignal(int signum)
                    633: {
1.1.1.2 ! root      634:     CPTR thistask = get_long(EXEC_sysbase + 276);
1.1       root      635:     if (signum != -1)
                    636:        return;
                    637:     put_long(thistask + 18, get_long(thistask + 18) & ~(1 << signum));
                    638: }
                    639: 
                    640: ULONG EXEC_SetSignal(ULONG newsig, ULONG exec_sigmask)
                    641: {
1.1.1.2 ! root      642:     CPTR task = get_long(EXEC_sysbase + 276);
1.1       root      643:     ULONG signals = get_long(task + 26);
                    644:     /* @@@ check SigExcept here */
                    645:     put_long(task + 26, (signals & ~exec_sigmask) | (newsig & exec_sigmask));
                    646:     return signals;
                    647: }
                    648: 
                    649: void EXEC_Signal(CPTR task, ULONG exec_sigmask)
                    650: {
                    651:     ULONG exec_sigs = get_long(task + 26);
                    652:     ULONG sigwait = get_long(task + 22);
1.1.1.2 ! root      653:     
        !           654:     if (task == 0) {
        !           655: /*     fprintf(stderr, "Signalling NULL task. Bad\n");*/
        !           656:        return;
        !           657:     }
1.1       root      658:     put_long(task + 26, exec_sigs | exec_sigmask);
                    659:     if (get_byte(task + 15) == TS_WAIT && (sigwait & exec_sigmask) != 0) {
                    660:        EXEC_Remove(task);
1.1.1.2 ! root      661:        put_byte(task + 15, TS_READY);
        !           662:        EXEC_Enqueue(EXEC_sysbase + 406, task);
1.1       root      663:        need_resched = 1;
                    664:        maybe_schedule();
                    665:     }
                    666: }
                    667: 
                    668: ULONG EXEC_Wait(ULONG exec_sigmask)
                    669: {
1.1.1.2 ! root      670:     CPTR task = get_long(EXEC_sysbase + 276);
1.1       root      671:     ULONG exec_sigs = get_long(task + 26);
                    672:     if ((exec_sigs & exec_sigmask) != 0) {
                    673:        put_long(task + 26, exec_sigs & ~exec_sigmask);
                    674:        return exec_sigs & exec_sigmask;
                    675:     }
1.1.1.2 ! root      676:     if (get_byte(EXEC_sysbase + 294) != 0xFF || get_byte(EXEC_sysbase + 295) != 0xFF)
1.1       root      677:     {
                    678:        fprintf(stderr, "Arrgh, task Wait()ing when it shouldn't\n");
                    679:     }
                    680:     if (intr_count || regs.s) {
                    681:        fprintf(stderr, "Arrgh, task Wait()ing when it _really_ shouldn't\n");
                    682:     }
                    683: 
                    684:     put_byte(task + 15, TS_WAIT);
                    685:     put_long(task + 22, exec_sigmask);
                    686:     schedule();
                    687:     exec_sigs = get_long(task + 26);
                    688:     if ((exec_sigs & exec_sigmask) != 0) {
                    689:        put_long(task + 26, exec_sigs & ~exec_sigmask);
                    690:        return exec_sigs & exec_sigmask;
                    691:     } 
                    692:     fprintf(stderr, "Bug: task woke up without signals\n");
                    693:     return 0;
                    694: }
                    695: 
1.1.1.2 ! root      696: static ULONG execl_SetSignal(void) { return EXEC_SetSignal(m68k_dreg(regs, 0), m68k_dreg(regs, 1)); }
        !           697: static ULONG execl_Signal(void) { EXEC_Signal(m68k_areg(regs, 1), m68k_dreg(regs, 0)); return 0; }
        !           698: static ULONG execl_Wait(void) { return EXEC_Wait(m68k_dreg(regs, 0)); }
        !           699: static ULONG execl_AllocSignal(void) { return EXEC_AllocSignal((BYTE)m68k_dreg(regs, 0)); }
        !           700: static ULONG execl_FreeSignal(void) { EXEC_FreeSignal((BYTE)m68k_dreg(regs, 0)); return 0; }
1.1       root      701: 
                    702: /*
                    703:  * Semaphores
                    704:  */
                    705: 
                    706: void EXEC_InitSemaphore(CPTR exec_sigsem)
                    707: {
                    708:     EXEC_NewList(exec_sigsem + 16);
                    709:     put_word(exec_sigsem + 14, 0);
                    710:     put_word(exec_sigsem + 44, 0xFFFF);
                    711: }
                    712: 
                    713: ULONG EXEC_AttemptSemaphore(CPTR exec_sigsem)
                    714: {
1.1.1.2 ! root      715:     CPTR task = get_long(EXEC_sysbase + 276);
1.1       root      716:     UWORD count = get_word(exec_sigsem + 44);
                    717:     if (count == 0xFFFF) {
                    718:        /* Semaphore free -> lock it */
                    719:        put_word(exec_sigsem + 44, 0);
                    720:        put_long(exec_sigsem + 40, task);
                    721:        put_word(exec_sigsem + 14, 1);
                    722:        return 1;
                    723:     }
                    724:     if (get_long(exec_sigsem + 40) == task) {
                    725:        /* Locked by same task -> Increment NestCount */
                    726:        put_word(exec_sigsem + 14, get_word(exec_sigsem + 14) + 1);
                    727:        return 1;
                    728:     }
                    729:     return 0;
                    730: }
                    731: 
                    732: void EXEC_ObtainSemaphore(CPTR exec_sigsem)
                    733: {
1.1.1.2 ! root      734:     CPTR task = get_long(EXEC_sysbase + 276);
1.1       root      735:     UWORD count = get_word(exec_sigsem + 44);
1.1.1.2 ! root      736:     CPTR n;
        !           737: 
1.1       root      738:     if (count == 0xFFFF) {
                    739:        /* Semaphore free -> lock it */
                    740:        put_word(exec_sigsem + 44, 0);
                    741:        put_long(exec_sigsem + 40, task);
                    742:        put_word(exec_sigsem + 14, 1);
                    743:        return;
                    744:     }
                    745:     if (get_long(exec_sigsem + 40) == task) {
                    746:        /* Locked by same task -> Increment NestCount */
                    747:        put_word(exec_sigsem + 14, get_word(exec_sigsem + 14) + 1);
                    748:        return;
                    749:     }
                    750:     /* Need to wait. */
                    751:     /* @@@ None of the predefined signals in exec/tasks.h seem to be used
                    752:      * for this. We use 0x8000, which appears not to be used otherwise */
                    753:     put_word(exec_sigsem + 44, count + 1);
1.1.1.2 ! root      754:     n = EXEC_AllocMem(12, 0); /* Ugh... is there a cleaner way? */
        !           755:     put_long(n + 8, task);
        !           756:     EXEC_AddTail(exec_sigsem + 16, n);
1.1       root      757:     if (EXEC_Wait(0x8000) != 0x8000)
                    758:        fprintf(stderr, "BUG\n");
1.1.1.2 ! root      759:     EXEC_FreeMem(n, 12);
1.1       root      760:     /* Now it's mine, all mine! */
                    761:     put_long(exec_sigsem + 40, task);
                    762:     put_word(exec_sigsem + 14, 1);
                    763: }
                    764: 
                    765: void EXEC_ReleaseSemaphore(CPTR exec_sigsem)
                    766: {
                    767:     UWORD nest = get_word(exec_sigsem + 14);
                    768:     put_word(exec_sigsem + 14, nest - 1);
                    769:     if (nest == 1) {
                    770:        /* We're losing it. Signal the first task on the wait queue
                    771:         * (that one will in turn wake the next, etc.) */
1.1.1.2 ! root      772:        CPTR task = get_long(EXEC_RemHead(exec_sigsem + 16) + 8);
1.1       root      773:        UWORD count = get_word(exec_sigsem + 44);
                    774:        put_word(exec_sigsem + 44, count - 1);
                    775:        if (task) {
                    776:            EXEC_Signal(task, 0x8000);
                    777:        }
                    778:     }
                    779: }
                    780: 
1.1.1.2 ! root      781: /* Assumption: Semaphores on the list are only handled through these two
        !           782:  * functions. I don't see how it could work reliably otherwise. But I don't
        !           783:  * see either why these functions ought to be used: You might as well have
        !           784:  * one semaphore instead of a list of them.
        !           785:  * For safety, these functions try hard to function even in cases where they
        !           786:  * might otherwise deadlock or break.
        !           787:  * @@@ what should happen if the task already owns semaphores on the list?
        !           788:  */
        !           789: 
        !           790: void EXEC_ObtainSemaphoreList(CPTR l)
        !           791: {
        !           792:     CPTR task = get_long(EXEC_sysbase + 276);
        !           793:     CPTR n;
        !           794: 
        !           795:     int retry;
        !           796:     EXEC_Forbid();
        !           797:     do {
        !           798:        retry = 0;
        !           799:        /* See if any semaphores on the list are locked. If so, go to
        !           800:         * sleep */
        !           801:        n = get_long(l);
        !           802:        while(get_long(n) != 0) {
        !           803:            if (get_word(n + 44) != 0xFFFF && get_long(n + 40) != task) {
        !           804:                /* Semaphore is locked. Obtain it the normal way */
        !           805:                EXEC_Permit();
        !           806:                EXEC_ObtainSemaphore(n);
        !           807:                EXEC_ReleaseSemaphore(n);
        !           808:                EXEC_Forbid();
        !           809:                retry = 1;
        !           810:                break;
        !           811:            }
        !           812:            n = get_long(n);
        !           813:        }
        !           814:     } while (retry);
        !           815:     /* All semaphores on the list are unlocked. */
        !           816:     for (n = get_long(l); get_long(n) != 0; n = get_long(n)) {
        !           817:        put_word(n + 44, get_word(n + 44) + 1);
        !           818:        put_long(n + 40, task);
        !           819:        put_word(n + 14, get_word(n + 14) + 1);
        !           820:     }
        !           821:     EXEC_Permit();
        !           822: }
        !           823: 
        !           824: void EXEC_ReleaseSemaphoreList(CPTR l)
        !           825: {
        !           826:     CPTR n;
        !           827: 
        !           828:     EXEC_Forbid();
        !           829:     for (n = get_long(l); get_long(n) != 0; n = get_long(n)) {
        !           830:        EXEC_ReleaseSemaphore(n);
        !           831:     }
        !           832:     EXEC_Permit();
        !           833: }
        !           834: 
        !           835: static ULONG execl_ObtainSemaphore(void) { EXEC_ObtainSemaphore(m68k_areg(regs, 0)); return 0; }
        !           836: static ULONG execl_ReleaseSemaphore(void) { EXEC_ReleaseSemaphore(m68k_areg(regs, 0)); return 0; }
        !           837: static ULONG execl_ObtainSemaphoreList(void) { EXEC_ObtainSemaphoreList(m68k_areg(regs, 0)); return 0; }
        !           838: static ULONG execl_ReleaseSemaphoreList(void) { EXEC_ReleaseSemaphoreList(m68k_areg(regs, 0)); return 0; }
        !           839: static ULONG execl_FindSemaphore(void) { return EXEC_FindName(EXEC_sysbase + 532, raddr(m68k_areg(regs, 1))); }
        !           840: static ULONG execl_InitSemaphore(void) { EXEC_InitSemaphore(m68k_areg(regs, 0)); return 0; }
        !           841: static ULONG execl_AttemptSemaphore(void) { return EXEC_AttemptSemaphore(m68k_areg(regs, 0)); }
        !           842: static ULONG execl_AddSemaphore(void) { put_byte(m68k_areg(regs, 1) + 8, NT_SIGNALSEM); EXEC_Enqueue(EXEC_sysbase + 532, m68k_areg(regs, 1)); return 0; }
1.1       root      843: 
                    844: /*
                    845:  * Messages and ports
                    846:  */
                    847: 
                    848: CPTR EXEC_GetMsg(CPTR port)
                    849: {
                    850:     return EXEC_RemHead(port + 20);
                    851: }
                    852: 
                    853: /* This is shared between PutMsg and ReplyMsg */
                    854: static void EXEC_doputmsg(CPTR port, CPTR msg)
                    855: {
                    856:     UBYTE flags = get_byte (port + 14);
                    857:     EXEC_AddTail(port + 20, msg);
                    858:     if (flags == 0)
                    859:        EXEC_Signal(get_long(port + 16), 1 << get_byte(port + 15));
                    860:     else if (flags == 1)
                    861:        fprintf(stderr, "PA_SOFTINT unsupported\n");
                    862:     
                    863: }
                    864: 
                    865: void EXEC_PutMsg(CPTR port, CPTR msg)
                    866: {
1.1.1.2 ! root      867:     put_byte(msg + 8, NT_MESSAGE);
1.1       root      868:     EXEC_doputmsg(port, msg);
                    869: }
                    870: 
                    871: void EXEC_ReplyMsg(CPTR msg)
1.1.1.2 ! root      872: {
        !           873:     CPTR p = get_long(msg + 14);
        !           874:     if (p == 0) {
        !           875:        put_byte(msg + 8, NT_FREEMSG);
        !           876:     } else {
        !           877:        put_byte(msg + 8, NT_REPLYMSG);
        !           878:        EXEC_doputmsg(p, msg);
        !           879:     }
1.1       root      880: }
                    881: 
                    882: CPTR EXEC_WaitPort(CPTR port)
                    883: {
                    884:     for (;;) {
                    885:        CPTR msg = get_long(port + 20);
                    886:        if (get_long(msg) != 0)
                    887:            return msg;
                    888:        if (get_byte(port + 14) != 0)
                    889:            fprintf(stderr, "Don't know how to WaitPort()\n");
                    890:        EXEC_Wait(1 << get_byte(port + 15));
                    891:     }
                    892: }
                    893: 
1.1.1.2 ! root      894: void EXEC_AddPort(CPTR port)
        !           895: {
        !           896:     put_byte(port + 8, NT_MSGPORT);
        !           897:     EXEC_Enqueue(EXEC_sysbase + 392, port);
        !           898:     EXEC_NewList(port + 20);
        !           899:     /* should we put the task into the appropriate place? */
        !           900: }
        !           901: 
        !           902: void EXEC_RemPort(CPTR port)
        !           903: {
        !           904:     EXEC_Remove(port);
        !           905: }
        !           906: 
        !           907: static ULONG execl_GetMsg(void) { return EXEC_GetMsg(m68k_areg(regs, 0)); }
        !           908: static ULONG execl_PutMsg(void) { EXEC_PutMsg(m68k_areg(regs, 0), m68k_areg(regs, 1)); return 0; }
        !           909: static ULONG execl_ReplyMsg(void) { EXEC_ReplyMsg(m68k_areg(regs, 1)); return 0; }
        !           910: static ULONG execl_WaitPort(void) { return EXEC_WaitPort(m68k_areg(regs, 0)); }
        !           911: static ULONG execl_FindPort(void) { return EXEC_FindName(EXEC_sysbase + 392, raddr(m68k_areg(regs, 1))); }
        !           912: static ULONG execl_AddPort(void) { EXEC_AddPort(m68k_areg(regs, 1)); return 0; }
        !           913: static ULONG execl_RemPort(void) { EXEC_RemPort(m68k_areg(regs, 1)); return 0; }
1.1       root      914: 
                    915: /*
                    916:  * I/O
                    917:  */
                    918: 
                    919: LONG EXEC_WaitIO(CPTR ioreq)
                    920: {
                    921:     /* The device is supposed to clear the IO_QUICK bit if it's going to
                    922:      * reply to the command */
                    923:     if ((get_byte(ioreq + 30) & 1) == 1)
                    924:        return (LONG)(BYTE)get_byte(ioreq + 31);
                    925: 
                    926:     for (;;) {
1.1.1.2 ! root      927:        if (get_byte(ioreq + 8) == NT_REPLYMSG)
1.1       root      928:            break;
                    929:        /* We'll just hope that this a) has a ReplyPort and b) that port
                    930:         * is of type PA_SIGNAL 
                    931:         * Don't WaitPort() here: WaitPort() returns a message, and we
                    932:         * aren't sure it's for us. */
                    933:        
                    934:        EXEC_Wait(1 << get_byte(get_long(ioreq + 14) + 15));
                    935:     }
                    936:     EXEC_Remove(ioreq);
                    937:     return (LONG)(BYTE)get_byte(ioreq + 31);
                    938: }
                    939: 
                    940: static void EXEC_BeginIO(CPTR ioreq)
                    941: {
                    942:     CPTR dev = get_long(ioreq + 20);
1.1.1.2 ! root      943:     m68k_areg(regs, 6) = dev;
        !           944:     m68k_areg(regs, 1) = ioreq;
1.1       root      945:     Call68k(dev - 30, 1);
1.1.1.2 ! root      946:     m68k_areg(regs, 6) = EXEC_sysbase;
1.1       root      947: }
                    948: 
1.1.1.2 ! root      949: LONG EXEC_DoIO(CPTR ioreq)
1.1       root      950: {
                    951:     put_byte(ioreq + 30, 1);
                    952:     EXEC_BeginIO(ioreq);
1.1.1.2 ! root      953:     return EXEC_WaitIO(ioreq);
1.1       root      954: }
1.1.1.2 ! root      955: 
1.1       root      956: void EXEC_SendIO(CPTR ioreq)
                    957: {
                    958:     put_byte(ioreq + 30, 0);
                    959:     EXEC_BeginIO(ioreq);
                    960: }
                    961: 
                    962: CPTR EXEC_CheckIO(CPTR ioreq)
                    963: {
                    964:     if ((get_byte(ioreq + 30) & 1) == 1)
                    965:        return ioreq;
1.1.1.2 ! root      966:     if (get_byte(ioreq + 8) == NT_REPLYMSG)
1.1       root      967:        return ioreq;
                    968:     return 0;
                    969: }
                    970: 
1.1.1.2 ! root      971: void EXEC_AbortIO(CPTR ioRequest)
        !           972: {
        !           973:     CPTR dev = get_long(ioRequest + 20);
        !           974:     m68k_areg(regs, 6) = dev;
        !           975:     m68k_areg(regs, 1) = ioRequest;
        !           976:     /* The example code returns a value here. What should we do with it? */
        !           977:     Call68k(dev - 36, 1);
        !           978:     m68k_areg(regs, 6) = EXEC_sysbase;
        !           979: }
        !           980: 
        !           981: static ULONG execl_WaitIO(void) { return EXEC_WaitIO(m68k_areg(regs, 1)); }
        !           982: static ULONG execl_DoIO(void) { return EXEC_DoIO(m68k_areg(regs, 1)); }
        !           983: static ULONG execl_SendIO(void) { EXEC_SendIO(m68k_areg(regs, 1)); return 0; }
        !           984: static ULONG execl_CheckIO(void) { return EXEC_CheckIO(m68k_areg(regs, 1)); }
        !           985: static ULONG execl_AbortIO(void) { EXEC_AbortIO(m68k_areg(regs, 1)); return 0; }
1.1       root      986: 
                    987: /*
                    988:  * Libraries
                    989:  */
                    990: 
                    991: void EXEC_SumLibrary(CPTR lib)
                    992: {
                    993:     CPTR start = lib - get_word(lib + 16);
                    994:     int len = get_word(lib + 16) + get_word(lib + 18);
                    995:     ULONG sum = 0;
                    996:     UWORD flags = get_word(lib + 14);
                    997:     
                    998:     if (flags & 1) /* SUMMING? */
                    999:        return;
                   1000:     if (!(flags & 4)) /* SUMUSED? */
                   1001:        return;
                   1002:     put_word(lib + 14, flags & ~2); /* mark as not changed */
                   1003:     /* Pretend the checksum is OK, I don't care enough */
                   1004: }
                   1005: 
                   1006: CPTR EXEC_SetFunction(CPTR lib, int funcOffset, CPTR function)
                   1007: {
                   1008:     CPTR oldfunc = get_long(lib + funcOffset + 2);
                   1009:     put_word(lib + funcOffset, 0x4EF9);
                   1010:     put_long(lib + funcOffset + 2, function);
                   1011:     put_word(lib + 14, get_word(lib + 14) | 2);
                   1012:     EXEC_SumLibrary(lib);
                   1013:     return oldfunc;
                   1014: }
                   1015: 
                   1016: void EXEC_AddLibrary(CPTR lib)
                   1017: {
1.1.1.2 ! root     1018:     EXEC_Enqueue(EXEC_sysbase + 378, lib);
1.1       root     1019:     put_word(lib + 14, 2); /* mark as changed */
                   1020:     EXEC_SumLibrary(lib);
                   1021: }
                   1022: 
                   1023: CPTR EXEC_OpenLibrary(char *name, int version)
                   1024: {
1.1.1.2 ! root     1025:     CPTR lib = EXEC_FindName(EXEC_sysbase + 378, name);
        !          1026:     
        !          1027:     if (lib != 0 && get_word(lib + 20) < version)
        !          1028:        return 0;
        !          1029:     
1.1       root     1030:     if (lib != 0) {
1.1.1.2 ! root     1031:        CPTR lib2;
        !          1032:        m68k_areg(regs, 6) = lib;
        !          1033:        m68k_dreg(regs, 0) = version;
        !          1034:        lib2 = Call68k(lib - 6, 1);
        !          1035:        if (lib2 == 0)
        !          1036:            lib = 0;
        !          1037:        else if (lib2 != lib)
        !          1038:            fprintf(stderr, "OpenLibrary: weirdness\n");
        !          1039:        m68k_areg(regs, 6) = EXEC_sysbase;
1.1       root     1040:     }
                   1041:     return lib;
                   1042: }
                   1043: 
                   1044: CPTR EXEC_OpenDevice(char *name, ULONG unit, CPTR ioRequest, ULONG flags)
                   1045: {
1.1.1.2 ! root     1046:     CPTR dev = EXEC_FindName(EXEC_sysbase + 350, name);
1.1       root     1047:     CPTR replyport = get_long(ioRequest + 14);
                   1048:     put_long(ioRequest + 20, dev);
                   1049:     put_byte(ioRequest + 31, 0);
                   1050:     put_byte(ioRequest + 30, flags); /* is this right? */
                   1051:     if (replyport == 0)
                   1052:        fprintf(stderr, "ioRequest has no ReplyPort\n");
                   1053:     else {
                   1054:        CPTR rtask = get_long(replyport + 16);
1.1.1.2 ! root     1055:        if (rtask == 0) {
1.1       root     1056:            fprintf(stderr, "replyTask == 0\n");
1.1.1.2 ! root     1057:            put_long(replyport + 16, get_long(EXEC_sysbase + 276));
        !          1058:        }
        !          1059:        else if (rtask != get_long(EXEC_sysbase + 276))
1.1       root     1060:            fprintf(stderr, "replyTask != current\n");
1.1.1.2 ! root     1061: /*     put_long(replyport + 16, get_long(EXEC_sysbase + 276));*/
1.1       root     1062:     }
                   1063:     if (dev != 0) {
1.1.1.2 ! root     1064:        m68k_areg(regs, 6) = dev;
        !          1065:        m68k_areg(regs, 1) = ioRequest;
        !          1066:        m68k_dreg(regs, 0) = unit;
        !          1067:        m68k_dreg(regs, 1) = flags;
        !          1068:        EXEC_Forbid();
1.1       root     1069:        dev = Call68k(dev - 6, 1);
1.1.1.2 ! root     1070:        EXEC_Permit();
        !          1071:        m68k_areg(regs, 6) = EXEC_sysbase;
1.1       root     1072:     }
                   1073:     return (LONG)(BYTE)get_byte(ioRequest + 31);
                   1074: }
                   1075: 
1.1.1.2 ! root     1076: /*
        !          1077:  * There seems to be some magic involved here. These functions are documented
        !          1078:  * as returning void. However, if we leave D0 unmodified by giving
        !          1079:  * TRAPFLAG_NORETVAL, there are bogus FreeMem calls; these go away if we
        !          1080:  * return 0 in D0 as the old code did. I guess these are really supposed to
        !          1081:  * return the value that was given to them by the library's Close routine
        !          1082:  * (for the DOS CloseDevice()/CloseLibrary() calls, probably)
        !          1083:  */
        !          1084: 
        !          1085: ULONG EXEC_CloseDevice(CPTR ioRequest)
        !          1086: {
        !          1087:     CPTR dev = get_long(ioRequest + 20);
        !          1088:     ULONG retval;
        !          1089:     
        !          1090:     m68k_areg(regs, 6) = dev;
        !          1091:     m68k_areg(regs, 1) = ioRequest;
        !          1092:     EXEC_Forbid();
        !          1093:     retval = Call68k(dev - 12, 1);
        !          1094:     EXEC_Permit();
        !          1095:     return retval;
        !          1096: }
        !          1097: 
        !          1098: ULONG EXEC_CloseLibrary(CPTR lib)
        !          1099: {
        !          1100:     ULONG retval;
        !          1101: 
        !          1102:     m68k_areg(regs, 6) = lib;
        !          1103:     EXEC_Forbid();
        !          1104:     retval = Call68k(lib - 12, 1);
        !          1105:     EXEC_Permit();
        !          1106:     return retval;
        !          1107: }
        !          1108: 
1.1       root     1109: void EXEC_AddDevice(CPTR lib)
                   1110: {
1.1.1.2 ! root     1111:     EXEC_Enqueue(EXEC_sysbase + 350, lib);
1.1       root     1112: }
                   1113: 
                   1114: void EXEC_AddResource(CPTR lib)
                   1115: {
1.1.1.2 ! root     1116:     EXEC_Enqueue(EXEC_sysbase + 336, lib);
1.1       root     1117: }
                   1118: 
                   1119: CPTR EXEC_OpenResource(char *name)
                   1120: {
1.1.1.2 ! root     1121:     CPTR lib = EXEC_FindName(EXEC_sysbase + 336, name);
1.1       root     1122:     return lib;
                   1123: }
                   1124: 
                   1125: void EXEC_MakeFunctions(CPTR target, CPTR funcarray, CPTR funcdispb)
                   1126: {
                   1127:     if (funcdispb != 0) {
                   1128:        WORD tmp;
                   1129:        for (;;) {
                   1130:            tmp = get_word(funcarray); funcarray += 2;
                   1131:            if (tmp == -1)
                   1132:                break;
                   1133:            target -= 6;
                   1134:            put_word(target, 0x4EF9); /* JMP.L */
                   1135:            put_long(target + 2, funcdispb + tmp);
                   1136:        }
                   1137:     } else {
                   1138:        CPTR tmp;
                   1139:        for (;;) {
                   1140:            tmp = get_long(funcarray); funcarray += 4;
                   1141:            if (tmp == (CPTR)-1)
                   1142:                break;
                   1143:            target -= 6;
                   1144:            put_word(target, 0x4EF9); /* JMP.L */
                   1145:            put_long(target + 2, tmp);
                   1146:        }
                   1147:     }
                   1148: }
                   1149: 
                   1150: CPTR EXEC_MakeLibrary(CPTR vectors, CPTR structure, CPTR init,
                   1151:                      unsigned long dsize, ULONG seglist_b)
                   1152: {
                   1153:     CPTR seglist = seglist_b << 2;
                   1154:     int vec_cnt = 0;
                   1155:     unsigned long negsize;
                   1156:     CPTR base, fdispb = 0, funcarray = vectors;
                   1157:     ULONG retval = 0;
                   1158: 
                   1159:     if (get_word (vectors) == (UWORD)-1) {
                   1160:        int offs = 2;
                   1161:        fdispb = vectors;
                   1162:        funcarray += 2;
                   1163:        while (get_word (vectors+offs) != (UWORD)-1) {
                   1164:            offs += 2;
                   1165:            vec_cnt++;
                   1166:        }
                   1167:     } else {
                   1168:        int offs = 0;
1.1.1.2 ! root     1169:        while (get_long (vectors+offs) != (ULONG)-1) {
1.1       root     1170:            offs += 4; 
                   1171:            vec_cnt++;
                   1172:        }
                   1173:     }
                   1174:     negsize = (vec_cnt * 6 + 3) & ~3;
                   1175:     dsize = (dsize + 3) & ~3;
                   1176: 
                   1177:     base = EXEC_AllocMem(negsize + dsize, MEMF_PUBLIC|MEMF_CLEAR);
                   1178:     if (base == 0) /* Uh oh */
                   1179:        return 0;
                   1180:     EXEC_MakeFunctions(base + negsize, funcarray, fdispb);
                   1181:     base += negsize;
                   1182:     put_word(base + 16, negsize);
                   1183:     put_word(base + 18, dsize);
                   1184:     if (structure != 0) {
                   1185:        /* Size is set to 0 so we won't clear it again */
                   1186:        EXEC_InitStruct(structure, base, 0);
                   1187:     }
                   1188:     if (init != 0) {
1.1.1.2 ! root     1189:        m68k_areg(regs, 6) = EXEC_sysbase;
        !          1190:        m68k_areg(regs, 0) = seglist; /* BCPL seglist here? */
        !          1191:        m68k_dreg(regs, 0) = base;
1.1       root     1192:        /* call it */
                   1193:        retval = Call68k(init, 0);
                   1194:     } else
                   1195:        retval = base;
                   1196:     
1.1.1.2 ! root     1197:     fprintf(stderr, "MakeLibrary: %s\n", raddr(get_long(base+10)));
1.1       root     1198:     return retval;
                   1199: }
                   1200: 
                   1201: CPTR EXEC_InitResident(CPTR resident, ULONG segList)
                   1202: {
                   1203:     UBYTE flags = get_byte(resident + 10);
1.1.1.2 ! root     1204: 
1.1       root     1205:     if (flags & 0x80) {
                   1206:        CPTR autoinit = get_long(resident + 22);
1.1.1.2 ! root     1207:        CPTR lib;
        !          1208:        lib = EXEC_MakeLibrary(get_long(autoinit + 4), get_long(autoinit + 8),
        !          1209:                               get_long(autoinit + 12), get_long(autoinit), 
        !          1210:                               segList >> 2);
        !          1211: 
        !          1212:        /* Is this right? Some libraries never get added if we don't do
        !          1213:         * this. */
        !          1214:        if (get_byte(resident + 12) == NT_LIBRARY)
        !          1215:            EXEC_AddLibrary(lib);
        !          1216:        else if (get_byte(resident + 12) == NT_DEVICE)
        !          1217:            EXEC_AddDevice(lib);
        !          1218:        else if (get_byte(resident + 12) == NT_RESOURCE)
        !          1219:            EXEC_AddResource(lib);
        !          1220:        return lib;
        !          1221: 
1.1       root     1222:     }
1.1.1.2 ! root     1223: 
        !          1224:     m68k_dreg(regs, 0) = 0;
        !          1225:     m68k_areg(regs, 0) = segList;
        !          1226:     m68k_areg(regs, 6) = EXEC_sysbase;
1.1       root     1227:     return Call68k(get_long(resident + 22), 0);
                   1228: }
                   1229: 
1.1.1.2 ! root     1230: CPTR EXEC_FindResident(char *name)
        !          1231: {
        !          1232:     CPTR rmods = get_long(EXEC_sysbase + 300);
        !          1233:     CPTR tmp2;
        !          1234: 
        !          1235:     if (name == NULL)
        !          1236:        return 0;
        !          1237: 
        !          1238:     for (; (tmp2 = get_long(rmods)) != 0; rmods += 4) {
        !          1239:        char *name2 = raddr(get_long(tmp2 + 14));
        !          1240:        if (strcmp(name, name2) == 0)
        !          1241:            return tmp2;
        !          1242:     }
        !          1243:     return 0;
        !          1244: }
        !          1245: 
        !          1246: static ULONG execl_MakeFunctions(void) { EXEC_MakeFunctions(m68k_areg(regs, 0), m68k_areg(regs, 1), m68k_areg(regs, 2)); return 0; }
        !          1247: static ULONG execl_SumLibrary(void) { EXEC_SumLibrary(m68k_areg(regs, 1)); return 0; }
        !          1248: static ULONG execl_SetFunction(void) { return EXEC_SetFunction(m68k_areg(regs, 1), (WORD)m68k_areg(regs, 0), m68k_dreg(regs, 0)); }
        !          1249: static ULONG execl_AddLibrary(void) { EXEC_AddLibrary(m68k_areg(regs, 1)); return 0; }
        !          1250: static ULONG execl_AddDevice(void) { EXEC_AddDevice(m68k_areg(regs, 1)); return 0; }
        !          1251: static ULONG execl_AddResource(void) { EXEC_AddResource(m68k_areg(regs, 1)); return 0; }
        !          1252: static ULONG execl_OpenLibrary(void) { return EXEC_OpenLibrary(raddr(m68k_areg(regs, 1)), m68k_dreg(regs, 0)); }
        !          1253: static ULONG execl_OldOpenLibrary(void) { return EXEC_OpenLibrary(raddr(m68k_areg(regs, 1)), 0); }
        !          1254: static ULONG execl_CloseLibrary(void) { return EXEC_CloseLibrary(m68k_areg(regs, 1)); }
        !          1255: static ULONG execl_OpenDevice(void) { return EXEC_OpenDevice(raddr(m68k_areg(regs, 0)), m68k_dreg(regs, 0), m68k_areg(regs, 1), m68k_dreg(regs, 1)); }
        !          1256: static ULONG execl_CloseDevice(void) { return EXEC_CloseDevice(m68k_areg(regs, 1)); }
        !          1257: static ULONG execl_OpenResource(void) { return EXEC_OpenResource(raddr(m68k_areg(regs, 1))); }
        !          1258: static ULONG execl_MakeLibrary(void) { return EXEC_MakeLibrary(m68k_areg(regs, 0), m68k_areg(regs, 1), m68k_areg(regs, 2), m68k_dreg(regs, 0), m68k_dreg(regs, 1)); }
        !          1259: static ULONG execl_FindResident(void) { return EXEC_FindResident(raddr(m68k_areg(regs, 1))); }
        !          1260: static ULONG execl_InitResident(void) { return EXEC_InitResident(m68k_areg(regs, 1), m68k_dreg(regs, 1)); }
1.1       root     1261: 
                   1262: /*
                   1263:  * Tasks
                   1264:  */
                   1265: 
                   1266: static void task_startup(void)
                   1267: {
                   1268:     m68k_setpc(regs.pc);
1.1.1.2 ! root     1269:     Call68k_retaddr(regs.pc, 0, get_long(m68k_areg(regs, 7) - 4));
1.1       root     1270:     fprintf(stderr, "Task fell through at the end\n");
                   1271: }
                   1272: 
1.1.1.2 ! root     1273: void EXEC_RemTask(CPTR task)
        !          1274: {
        !          1275:     if (task == 0)
        !          1276:        task = get_long(EXEC_sysbase + 276);
        !          1277:     /* We can't easily delete it here while we use it's stack. Let schedule()
        !          1278:       * do it. */
        !          1279:     put_byte(task + 15, TS_REMOVED);
        !          1280:     task_to_kill = find_newtask(task);
        !          1281:     schedule();
        !          1282: }
        !          1283: 
1.1       root     1284: CPTR EXEC_AddTask(CPTR task, CPTR initPC, CPTR finalPC)
                   1285: {
                   1286:     struct NewTask *nt = (struct NewTask *)malloc(sizeof (struct NewTask));
1.1.1.2 ! root     1287: 
1.1       root     1288:     nt->exectask = task;
                   1289:     nt->prev = &idle_task;
                   1290:     nt->next = idle_task.next;
                   1291:     idle_task.next->prev = nt;
                   1292:     idle_task.next = nt;
                   1293:     memset(&nt->regs, 0, sizeof (nt->regs));
                   1294:     nt->regs.pc = initPC;
1.1.1.2 ! root     1295:     m68k_areg(nt->regs, 7) = get_long(task + 54);
1.1       root     1296: 
                   1297:     if (finalPC == 0)
                   1298:        finalPC = 0xF0FFF0; /* standard "return from 68k mode" calltrap */
                   1299:     put_byte(task + 16, 0xFF);
                   1300:     put_byte(task + 17, 0xFF);
1.1.1.2 ! root     1301:     put_long(m68k_areg(nt->regs, 7) - 4, finalPC);
1.1       root     1302:     nt->stack = malloc(65536); /* @@@ make this smaller after checking that
                   1303:                                * no parts of the emulator need much stack
1.1.1.2 ! root     1304:                                * space */    
        !          1305:     EXEC_SETUP_SWS(nt);
        !          1306:     
1.1       root     1307:     put_byte(task + 15, TS_READY);
                   1308:     put_long(task + 18,0x0000FFFF); /* all tasks have the lower 16 signals allocated */
1.1.1.2 ! root     1309:     EXEC_Enqueue(EXEC_sysbase + 406, task);
1.1       root     1310:     need_resched = 1;
1.1.1.2 ! root     1311:     fprintf(stderr, "AddTask: %s\n", raddr(get_long(task + 10)));
1.1       root     1312:     maybe_schedule();
                   1313:     return task;
1.1.1.2 ! root     1314: }
        !          1315: 
        !          1316: int EXEC_SetTaskPri(CPTR task, int pri)
        !          1317: {
        !          1318:     int oldpri = get_byte(task + 9);
        !          1319: 
        !          1320:     if (task == get_long(EXEC_sysbase + 276)) {
        !          1321:        put_byte(task + 9, pri);
        !          1322:        return oldpri;
        !          1323:     }
        !          1324:     if (get_byte(task + 15) == TS_WAIT) {
        !          1325:        EXEC_Remove(task);
        !          1326:        put_byte(task + 9, pri);
        !          1327:        EXEC_Enqueue(EXEC_sysbase + 420, task);
        !          1328:        return oldpri;
        !          1329:     }
        !          1330:     EXEC_Remove(task);
        !          1331:     put_byte(task + 9, pri);
        !          1332:     EXEC_Enqueue(EXEC_sysbase + 406, task);
        !          1333:     schedule();
        !          1334:     return oldpri;
1.1       root     1335: }
                   1336: 
                   1337: CPTR EXEC_FindTask(char *name)
                   1338: {
                   1339:     char *n;
                   1340:     CPTR v;
                   1341: 
1.1.1.2 ! root     1342:     if (name == NULL || ((n = raddr(get_long(get_long(EXEC_sysbase + 276) + 10))) != NULL
1.1       root     1343:                         && strcmp(n, name) == 0))
1.1.1.2 ! root     1344:        return get_long(EXEC_sysbase + 276);
1.1       root     1345:     
1.1.1.2 ! root     1346:     v = EXEC_FindName(EXEC_sysbase + 406, name); /* ready tasks */
1.1       root     1347:     if (v != 0)
                   1348:        return v;
1.1.1.2 ! root     1349:     return EXEC_FindName(EXEC_sysbase + 420, name); /* waiting tasks */
1.1       root     1350: }
                   1351: 
1.1.1.2 ! root     1352: static ULONG execl_FindTask(void) { return EXEC_FindTask(raddr(m68k_areg(regs, 1))); }
        !          1353: static ULONG execl_AddTask(void) { return EXEC_AddTask(m68k_areg(regs, 1), m68k_areg(regs, 2), m68k_areg(regs, 3)); }
        !          1354: static ULONG execl_RemTask(void) { EXEC_RemTask(m68k_areg(regs, 1)); return 0; }
        !          1355: static ULONG execl_SetTaskPri(void) { return EXEC_SetTaskPri(m68k_areg(regs, 1), (BYTE)m68k_dreg(regs, 0)); }
1.1       root     1356: 
                   1357: ULONG EXEC_Forbid(void)
                   1358: {
1.1.1.2 ! root     1359:     int count = (BYTE)get_byte(EXEC_sysbase + 295);
1.1       root     1360:     count++;
1.1.1.2 ! root     1361:     put_byte(EXEC_sysbase + 295, count);
1.1       root     1362:     return 0; 
                   1363: }
                   1364: ULONG EXEC_Permit(void) 
                   1365: {
1.1.1.2 ! root     1366:     int count = (BYTE)get_byte(EXEC_sysbase + 295);
1.1       root     1367:     if (count == -1)
                   1368:        fprintf(stderr, "Too many Permit() calls\n");
                   1369:     else
                   1370:        count--;
1.1.1.2 ! root     1371:     put_byte(EXEC_sysbase + 295, count);    
1.1       root     1372:     maybe_schedule();
                   1373:     return 0;
                   1374: }
                   1375: 
                   1376: ULONG EXEC_Disable(void) 
                   1377: {
1.1.1.2 ! root     1378:     int count = (BYTE)get_byte(EXEC_sysbase + 294);
1.1       root     1379:     count++;
1.1.1.2 ! root     1380:     put_byte(EXEC_sysbase + 294, count);
1.1       root     1381:     put_word(0xDFF09A, 0x4000);
                   1382:     return 0;
                   1383: }
                   1384: 
                   1385: ULONG EXEC_Enable(void)
                   1386: {
1.1.1.2 ! root     1387:     int count = (BYTE)get_byte(EXEC_sysbase + 294);
1.1       root     1388:     if (count == -1)
                   1389:        fprintf(stderr, "Too many Enable() calls\n");
                   1390:     else
                   1391:        count--;
                   1392:     if (count == -1)
                   1393:        put_word(0xDFF09A, 0xC000);
1.1.1.2 ! root     1394:     put_byte(EXEC_sysbase + 294, count);
1.1       root     1395:     maybe_schedule();
                   1396:     return 0;
                   1397: }
1.1.1.2 ! root     1398: 
        !          1399: /*
        !          1400:  * Annoyances...
        !          1401:  */
        !          1402: 
        !          1403: enum rdf_state { rdf_flags, rdf_width, rdf_limit, rdf_type };
        !          1404: 
        !          1405: CPTR EXEC_RawDoFormat(UBYTE *fstr, CPTR data, CPTR pcp, ULONG pcd)
        !          1406: {
        !          1407:     if (fstr == NULL)
        !          1408:        return data;
        !          1409:     for (;;) {
        !          1410:        UBYTE c = *fstr++;
        !          1411: 
        !          1412:        if (c == 0)
        !          1413:            break;
        !          1414: 
        !          1415:        if (c == '%') {
        !          1416:            enum rdf_state rdfs = rdf_flags;
        !          1417:            int ljust = 0, fill0 = 0, islong = 0;
        !          1418:            int w = 0, lim = 0, havelim = 0;
        !          1419: 
        !          1420:            for (;;) {
        !          1421:                c = *fstr++;
        !          1422:                
        !          1423:                if (c == 0)
        !          1424:                    break;
        !          1425:                
        !          1426:                if (rdfs == rdf_flags) {
        !          1427:                    rdfs = rdf_width;
        !          1428:                    if (c == '-') {
        !          1429:                        ljust = 1;
        !          1430:                        continue;
        !          1431:                    }
        !          1432:                }
        !          1433:                if (rdfs == rdf_width && c == '.') {
        !          1434:                    rdfs = rdf_limit;
        !          1435:                    continue;
        !          1436:                } else if (rdfs == rdf_width && isdigit(c)) {
        !          1437:                    w = w*10 + c - '0';
        !          1438:                    if (w == 0)
        !          1439:                        fill0 = 1;
        !          1440:                    continue;
        !          1441:                } else if (rdfs == rdf_limit && isdigit(c)) {
        !          1442:                    lim = lim*10 + c - '0';
        !          1443:                    havelim = 1;
        !          1444:                    continue;
        !          1445:                } else if ((rdfs == rdf_limit || rdfs == rdf_width) && c == 'l') {
        !          1446:                    islong = 1;
        !          1447:                    rdfs = rdf_type;
        !          1448:                    continue;
        !          1449:                }
        !          1450:                switch (c) {
        !          1451:                    CPTR tmp;
        !          1452:                    ULONG tmp1;
        !          1453:                    unsigned int tmpl;
        !          1454:                    char tmps1[20], tmps2[20], *tmpsp;
        !          1455: 
        !          1456:                 case 'b':
        !          1457:                    tmp = get_long(data); 
        !          1458:                    data += 4;
        !          1459:                    tmpl = get_byte(tmp++);
        !          1460:                    for(; tmpl > 0; tmpl--) {
        !          1461:                        m68k_dreg(regs, 0) = get_byte(tmp++);
        !          1462:                        m68k_areg(regs, 3) = pcd;
        !          1463:                        Call68k(pcp, 0);
        !          1464:                    }
        !          1465:                    break;
        !          1466: 
        !          1467:                 case 'd':
        !          1468:                 case 'u':
        !          1469:                 case 'x':
        !          1470:                    if (islong) {
        !          1471:                        tmp1 = get_long(data); data += 4;
        !          1472:                    } else {
        !          1473:                        tmp1 = get_word(data); data += 2;
        !          1474:                        if (c == 'd')
        !          1475:                            tmp1 = (LONG)(WORD)tmp1;
        !          1476:                    }
        !          1477:                    tmpsp = tmps1;
        !          1478:                    *tmpsp++ = '%';
        !          1479:                    if (fill0)
        !          1480:                        *tmpsp++ = '0';
        !          1481:                    if (w != 0)
        !          1482:                        sprintf(tmpsp, "%d", w);
        !          1483:                    tmpsp += strlen(tmpsp);
        !          1484:                    *tmpsp++ = c;
        !          1485:                    *tmpsp++ = 0;
        !          1486:                    sprintf(tmps2, tmps1, tmp1);
        !          1487:                    for (tmpsp = tmps2; ;) {
        !          1488:                        m68k_dreg(regs, 0) = *tmpsp++;
        !          1489:                        if (m68k_dreg(regs, 0) == 0)
        !          1490:                            break;
        !          1491:                        m68k_areg(regs, 3) = pcd;
        !          1492:                        Call68k(pcp, 0);                        
        !          1493:                    }
        !          1494:                    break;
        !          1495: 
        !          1496:                 case 's':
        !          1497:                    tmp = get_long(data); 
        !          1498:                    data += 4;
        !          1499:                    for(;!havelim || lim-- > 0;) {
        !          1500:                        m68k_dreg(regs, 0) = get_byte(tmp++);
        !          1501:                        if (m68k_dreg(regs, 0) == 0)
        !          1502:                            break;
        !          1503:                        m68k_areg(regs, 3) = pcd;
        !          1504:                        Call68k(pcp, 0);
        !          1505:                    }
        !          1506:                    break;
        !          1507: 
        !          1508:                 case 'c':
        !          1509:                    if (islong) {
        !          1510:                        m68k_dreg(regs, 0) = get_long(data); data += 4;
        !          1511:                    } else {
        !          1512:                        m68k_dreg(regs, 0) = get_word(data); data += 2;
        !          1513:                    }
        !          1514:                    m68k_areg(regs, 3) = pcd;
        !          1515:                    Call68k(pcp, 0);
        !          1516:                }
        !          1517:                break;
        !          1518:            }
        !          1519: 
        !          1520:        } else {
        !          1521:            m68k_dreg(regs, 0) = c;
        !          1522:            m68k_areg(regs, 3) = pcd;
        !          1523:            Call68k(pcp, 0);
        !          1524:        }
        !          1525:     }
        !          1526:     return data;
        !          1527: }
        !          1528: 
        !          1529: static ULONG execl_RawDoFormat(void) 
        !          1530: {
        !          1531:     return EXEC_RawDoFormat((UBYTE *)raddr(m68k_areg(regs, 0)), m68k_areg(regs, 1), m68k_areg(regs, 2), m68k_areg(regs, 3)); 
        !          1532: }
        !          1533: 
1.1       root     1534: /*
                   1535:  *  Initialization
                   1536:  */
                   1537: static ULONG execlib_init(void)
                   1538: {
1.1.1.2 ! root     1539:     EXEC_sysbase = get_long(4);
        !          1540: #if 1
1.1       root     1541:     /* CopyMem and CopyMemQuick */
1.1.1.2 ! root     1542:     libemu_InstallFunctionFlags(execl_CopyMem, EXEC_sysbase, -630, 0, "CopyMem");
        !          1543:     libemu_InstallFunctionFlags(execl_CopyMem, EXEC_sysbase, -624, 0, "CopyMem");
        !          1544:     libemu_InstallFunctionFlags(execl_Allocate, EXEC_sysbase, -186, 0, "Allocate");
        !          1545:     libemu_InstallFunctionFlags(execl_AllocMem, EXEC_sysbase, -198, 0, "AllocMem");
        !          1546:     libemu_InstallFunctionFlags(execl_Deallocate, EXEC_sysbase, -192, 0, "Deallocate");
        !          1547:     libemu_InstallFunctionFlags(execl_FreeMem, EXEC_sysbase, -210, 0, "FreeMem");
        !          1548:     libemu_InstallFunctionFlags(execl_AvailMem, EXEC_sysbase, -216, 0, "AvailMem");
1.1       root     1549:     
                   1550:     /* List management */
1.1.1.2 ! root     1551:     libemu_InstallFunctionFlags(execl_Insert, EXEC_sysbase, -234, TRAPFLAG_NORETVAL, "Insert");
        !          1552:     libemu_InstallFunctionFlags(execl_AddHead, EXEC_sysbase, -240, TRAPFLAG_NORETVAL, "AddHead");
        !          1553:     libemu_InstallFunctionFlags(execl_AddTail, EXEC_sysbase, -246, TRAPFLAG_NORETVAL, "AddTail");
        !          1554:     libemu_InstallFunctionFlags(execl_Enqueue, EXEC_sysbase, -270, TRAPFLAG_NORETVAL, "Enqueue");
        !          1555:     libemu_InstallFunctionFlags(execl_RemHead, EXEC_sysbase, -258, 0, "RemHead");
        !          1556:     libemu_InstallFunctionFlags(execl_RemTail, EXEC_sysbase, -264, 0, "RemTail");
        !          1557:     libemu_InstallFunctionFlags(execl_Remove, EXEC_sysbase, -252, TRAPFLAG_NORETVAL, "Remove");
        !          1558:     libemu_InstallFunctionFlags(execl_FindName, EXEC_sysbase, -276, 0, "FindName");
1.1       root     1559:     
                   1560:     /* Signals */
1.1.1.2 ! root     1561:     libemu_InstallFunctionFlags(execl_AllocSignal, EXEC_sysbase, -330, 0, "AllocSignal");
        !          1562:     libemu_InstallFunctionFlags(execl_FreeSignal, EXEC_sysbase, -336, 0, "FreeSignal");
1.1       root     1563: 
                   1564:     /* Semaphores */
1.1.1.2 ! root     1565:     libemu_InstallFunctionFlags(execl_FindSemaphore, EXEC_sysbase, -594, 0, "FindSemaphore");
        !          1566:     libemu_InstallFunctionFlags(execl_InitSemaphore, EXEC_sysbase, -558, 0, "InitSemaphore");
        !          1567:     libemu_InstallFunctionFlags(execl_AddSemaphore, EXEC_sysbase, -600, TRAPFLAG_NORETVAL, "AddSemaphore");
1.1       root     1568: 
                   1569:     /* Messages/Ports */
1.1.1.2 ! root     1570:     libemu_InstallFunctionFlags(execl_FindPort, EXEC_sysbase, -390, 0, "FindPort");
        !          1571:     libemu_InstallFunctionFlags(execl_GetMsg, EXEC_sysbase, -372, 0, "GetMsg");
1.1       root     1572: 
                   1573:     /* Libraries */
1.1.1.2 ! root     1574:     libemu_InstallFunctionFlags(execl_MakeFunctions, EXEC_sysbase, -90, 0, "MakeFunctions");
        !          1575:     libemu_InstallFunctionFlags(execl_SumLibrary, EXEC_sysbase, -426, TRAPFLAG_NORETVAL, "SumLibrary");
        !          1576:     libemu_InstallFunctionFlags(execl_SetFunction, EXEC_sysbase, -420, 0, "SetFunction");
1.1       root     1577:     
                   1578:     /* Tasks */
1.1.1.2 ! root     1579:     libemu_InstallFunctionFlags(execl_FindTask, EXEC_sysbase, -294, 0, "FindTask");
1.1       root     1580: 
                   1581:     /* Interrupts */
1.1.1.2 ! root     1582:     libemu_InstallFunctionFlags(execl_SetIntVector, EXEC_sysbase, -162, 0, "SetIntVector");
        !          1583:     libemu_InstallFunctionFlags(execl_AddIntServer, EXEC_sysbase, -168, TRAPFLAG_NORETVAL, "AddIntServer");
        !          1584:     libemu_InstallFunctionFlags(execl_RemIntServer, EXEC_sysbase, -174, 0, "RemIntServer");
1.1       root     1585:     
                   1586:     /* Miscellaneous */
1.1.1.2 ! root     1587:     libemu_InstallFunctionFlags(execl_InitStruct, EXEC_sysbase, -78, 0, "InitStruct");
        !          1588:     libemu_InstallFunctionFlags(execl_GetCC, EXEC_sysbase, -528, TRAPFLAG_NORETVAL|TRAPFLAG_NOREGSAVE, "InitStruct");
        !          1589: #elif 0
        !          1590:     libemu_InstallFunctionFlags(NULL, EXEC_sysbase, -564, TRAPFLAG_NORETVAL, "ObtainSemaphore");
        !          1591:     libemu_InstallFunctionFlags(NULL, EXEC_sysbase, -570, TRAPFLAG_NORETVAL, "ReleaseSemaphore");
        !          1592:     libemu_InstallFunctionFlags(NULL, EXEC_sysbase, -576, 0, "AttemptSemaphore");
        !          1593:     libemu_InstallFunctionFlags(NULL, EXEC_sysbase, -582, TRAPFLAG_NORETVAL, "ObtainSemaphoreList");
        !          1594:     libemu_InstallFunctionFlags(NULL, EXEC_sysbase, -588, TRAPFLAG_NORETVAL, "ReleaseSemaphoreList");
        !          1595: #endif
1.1       root     1596:     return 0;
                   1597: }
                   1598: 
1.1.1.2 ! root     1599: static ULONG execl_Open(void) { return EXEC_sysbase; }
        !          1600: 
1.1       root     1601: static ULONG execlib_init2(void)
                   1602: {
1.1.1.2 ! root     1603:     EXEC_sysbase = get_long(4);
1.1       root     1604:     
1.1.1.2 ! root     1605:     libemu_InstallFunctionFlags(execl_Open, EXEC_sysbase, -6, 0, "Open");
        !          1606:     libemu_InstallFunctionFlags(execl_AllocEntry, EXEC_sysbase, -222, 0, "AllocEntry");
        !          1607:     libemu_InstallFunctionFlags(execl_AddMemList, EXEC_sysbase, -618, 0, "AddMemList");
        !          1608: 
        !          1609:     libemu_InstallFunctionFlags(execl_AddLibrary, EXEC_sysbase, -396, TRAPFLAG_NORETVAL, "AddLibrary");
        !          1610:     libemu_InstallFunctionFlags(execl_AddDevice, EXEC_sysbase, -432, TRAPFLAG_NORETVAL, "AddDevice");
        !          1611:     libemu_InstallFunctionFlags(execl_AddResource, EXEC_sysbase, -486, TRAPFLAG_NORETVAL, "AddResource");
        !          1612:     libemu_InstallFunctionFlags(execl_OpenLibrary, EXEC_sysbase, -552, 0, "OpenLibrary");
        !          1613:     libemu_InstallFunctionFlags(execl_OldOpenLibrary, EXEC_sysbase, -408, 0, "OldOpenLibrary");
        !          1614:     libemu_InstallFunctionFlags(execl_OpenDevice, EXEC_sysbase, -444, 0, "OpenDevice");
        !          1615:     libemu_InstallFunctionFlags(execl_CloseDevice, EXEC_sysbase, -450, 0, "CloseDevice");
        !          1616:     libemu_InstallFunctionFlags(execl_OpenResource, EXEC_sysbase, -498, 0, "OpenResource");
        !          1617:     libemu_InstallFunctionFlags(execl_MakeLibrary, EXEC_sysbase, -84, 0, "MakeLibrary");
        !          1618:     libemu_InstallFunctionFlags(execl_CloseLibrary, EXEC_sysbase, -414, 0, "CloseLibrary");
        !          1619: 
        !          1620:     libemu_InstallFunctionFlags(execl_RawDoFormat, EXEC_sysbase, -522, 0, "RawDoFmt");
        !          1621:     libemu_InstallFunctionFlags(execl_InitResident, EXEC_sysbase, -102, 0, "InitResident");
        !          1622: 
        !          1623:     libemu_InstallFunctionFlags(EXEC_Disable, EXEC_sysbase, -120, TRAPFLAG_NORETVAL, "");
        !          1624:     libemu_InstallFunctionFlags(EXEC_Enable, EXEC_sysbase, -126, TRAPFLAG_NORETVAL, "");
        !          1625:     libemu_InstallFunctionFlags(EXEC_Permit, EXEC_sysbase, -138, TRAPFLAG_NORETVAL, "Permit");
        !          1626:     libemu_InstallFunctionFlags(EXEC_Forbid, EXEC_sysbase, -132, TRAPFLAG_NORETVAL, "Forbid");
        !          1627: 
        !          1628:     libemu_InstallFunctionFlags(execl_AddTask, EXEC_sysbase, -282, 0, "AddTask");
        !          1629:     libemu_InstallFunctionFlags(execl_RemTask, EXEC_sysbase, -288, TRAPFLAG_NORETVAL, "RemTask");
        !          1630:     libemu_InstallFunctionFlags(execl_SetTaskPri, EXEC_sysbase, -300, 0, "SetTaskPri");
        !          1631: 
        !          1632:     libemu_InstallFunctionFlags(execl_SetSignal, EXEC_sysbase, -306, 0, "SetSignal");
        !          1633:     libemu_InstallFunctionFlags(execl_Signal, EXEC_sysbase, -324, TRAPFLAG_NORETVAL, "Signal");
        !          1634:     libemu_InstallFunctionFlags(execl_Wait, EXEC_sysbase, -318, 0, "Wait");
        !          1635: 
        !          1636:     libemu_InstallFunctionFlags(execl_PutMsg, EXEC_sysbase, -366, 0, "PutMsg");
        !          1637:     libemu_InstallFunctionFlags(execl_ReplyMsg, EXEC_sysbase, -378, 0, "ReplyMsg");
        !          1638:     libemu_InstallFunctionFlags(execl_WaitPort, EXEC_sysbase, -384, 0, "WaitPort");
        !          1639:     libemu_InstallFunctionFlags(execl_AddPort, EXEC_sysbase, -354, TRAPFLAG_NORETVAL, "AddPort");
        !          1640:     libemu_InstallFunctionFlags(execl_RemPort, EXEC_sysbase, -360, TRAPFLAG_NORETVAL, "RemPort");
        !          1641: 
        !          1642:     libemu_InstallFunctionFlags(execl_WaitIO, EXEC_sysbase, -474, 0, "WaitIO");
        !          1643:     libemu_InstallFunctionFlags(execl_DoIO, EXEC_sysbase, -456, 0, "DoIO");
        !          1644:     libemu_InstallFunctionFlags(execl_SendIO, EXEC_sysbase, -462, TRAPFLAG_NORETVAL, "SendIO");
        !          1645:     libemu_InstallFunctionFlags(execl_CheckIO, EXEC_sysbase, -468, 0, "CheckIO");
        !          1646:     libemu_InstallFunctionFlags(execl_AbortIO, EXEC_sysbase, -468, 0, "AbortIO");
        !          1647: 
        !          1648:     libemu_InstallFunctionFlags(execl_ObtainSemaphore, EXEC_sysbase, -564, TRAPFLAG_NORETVAL, "ObtainSemaphore");
        !          1649:     libemu_InstallFunctionFlags(execl_ReleaseSemaphore, EXEC_sysbase, -570, TRAPFLAG_NORETVAL, "ReleaseSemaphore");
        !          1650:     libemu_InstallFunctionFlags(execl_AttemptSemaphore, EXEC_sysbase, -576, 0, "AttemptSemaphore");
        !          1651:     libemu_InstallFunctionFlags(execl_ObtainSemaphoreList, EXEC_sysbase, -582, TRAPFLAG_NORETVAL, "ObtainSemaphoreList");
        !          1652:     libemu_InstallFunctionFlags(execl_ReleaseSemaphoreList, EXEC_sysbase, -588, TRAPFLAG_NORETVAL, "ReleaseSemaphoreList");
1.1       root     1653: 
1.1.1.2 ! root     1654:     libemu_InstallFunctionFlags(execl_FindResident, EXEC_sysbase, -96, 0, "FindResident");
1.1       root     1655:     return 0;
                   1656: }
                   1657: 
                   1658: /*
                   1659:  * These functions are one day going to bootstrap the emulated Exec
                   1660:  */
                   1661: 
                   1662: #define NR_EXEC_FUNCTIONS 105 /* V34 (1.3) maximum */
                   1663: 
                   1664: static ULONG EXEC_ENOSYS(void)
                   1665: {
                   1666:     fprintf(stderr, "Not a system call\n");
                   1667:     return 0;
                   1668: }
                   1669: 
                   1670: static ULONG EXEC_StandardIntVec(void)
                   1671: {
1.1.1.2 ! root     1672:     int num = m68k_areg(regs, 1);
1.1       root     1673:     /* Call the IntHandlers */
                   1674:     return 0;
                   1675: }
                   1676: 
1.1.1.2 ! root     1677: static int trace_ints = 0;
        !          1678: 
1.1       root     1679: static ULONG EXEC_IntTrap(void)
                   1680: {
1.1.1.2 ! root     1681:     struct regstruct rtmp = regs;
        !          1682:     struct flag_struct ftmp = regflags;
        !          1683:     
1.1       root     1684:     UWORD intsreq = get_word(0xDFF01E) & get_word(0xDFF01C);
1.1.1.2 ! root     1685:     int i, do_timer = 0;
1.1       root     1686:     intr_count++;
1.1.1.2 ! root     1687: 
        !          1688:     if ((intena & 0x4000) == 0)
        !          1689:        fprintf(stderr, "Interrupt came in with interrupts off (%x, %x)!\n", get_byte(EXEC_sysbase + 294), get_byte(EXEC_sysbase + 295));
        !          1690:     
        !          1691:     TIMER_block();
        !          1692:     
        !          1693:     if (regs.spcflags & SPCFLAG_TIMER) {
        !          1694:        regs.spcflags &= ~SPCFLAG_TIMER;
        !          1695:        do_timer = 1;
        !          1696:     }
        !          1697:     
        !          1698:     TIMER_unblock();
        !          1699: 
        !          1700:     if (do_timer)
        !          1701:        TIMER_Interrupt();
1.1       root     1702:     
                   1703:     for (i = 13; i >= 0; i--) {
                   1704:        if ((intsreq & (1 << i)) != 0) {
1.1.1.2 ! root     1705:            if (trace_ints)
        !          1706:                fprintf(stderr, "INT: %d\n", i);
        !          1707:            /* Is this a server chain? */
1.1       root     1708:            if (i == 3 || i == 4 || i == 5 || i == 13 || i == 15) {
1.1.1.2 ! root     1709:                CPTR slist = get_long(EXEC_sysbase + 84 + 12*i);
1.1       root     1710:                CPTR snode = get_long(slist);
                   1711:                for (;;) {
                   1712:                    if (get_long(snode) == 0)
                   1713:                        break;
1.1.1.2 ! root     1714:                    m68k_areg(regs, 0) = 0xDFF000;
        !          1715:                    m68k_areg(regs, 5) = get_long(snode + 18);
        !          1716:                    m68k_areg(regs, 1) = get_long(snode + 14);
        !          1717:                    Call68k(m68k_areg(regs, 5), 0);
1.1       root     1718:                    if (ZFLG == 0)
                   1719:                        break;
                   1720:                    snode = get_long(snode);
                   1721:                }
                   1722:                put_word(0xDFF09C, 1 << i);
                   1723:            } else {
1.1.1.2 ! root     1724:                CPTR intnode = get_long(EXEC_sysbase + 84 + 12*i + 8);
        !          1725:                /* Blitter interrupts happen before vector is set up :-/ */
        !          1726:                if (intnode != 0) {
        !          1727:                    m68k_dreg(regs, 1) = intsreq;
        !          1728:                    m68k_areg(regs, 1) = get_long(intnode + 14);
        !          1729:                    m68k_areg(regs, 0) = 0xDFF000;
        !          1730:                    m68k_areg(regs, 5) = get_long(intnode + 18);
        !          1731:                    m68k_areg(regs, 6) = EXEC_sysbase;
        !          1732:                    Call68k(m68k_areg(regs, 5), 0);
        !          1733:                }
1.1       root     1734:            }
                   1735:            break;
                   1736:        }
                   1737:     }
                   1738:     if (i < 0)
                   1739:        fprintf(stderr, "So what interrupt am I supposed to serve?\n");
                   1740:     intr_count--;
1.1.1.2 ! root     1741:     
        !          1742:     /* This usually is a great indicator that the ExecBase pointer at
        !          1743:      * address 4 has been messed with... */
        !          1744:     if ((intena & 0x4000) == 0)
        !          1745:        fprintf(stderr, "Interrupt left interrupts off (%x, %x)!\n", get_byte(EXEC_sysbase + 294), get_byte(EXEC_sysbase + 295));
        !          1746:     regflags = ftmp;
        !          1747:     regs = rtmp;
        !          1748:     /* Perform a RTE */
        !          1749:     {
        !          1750:        CPTR sra = m68k_areg(regs, 7);
        !          1751:        regs.sr = get_word(sra);
        !          1752:        m68k_setpc_rte(get_long(sra+2));
        !          1753:        m68k_areg(regs, 7) = sra + 6;
        !          1754:        MakeFromSR();
        !          1755:     }
        !          1756: 
1.1       root     1757:     maybe_schedule();
1.1.1.2 ! root     1758:     return 0; /* ignored */
1.1       root     1759: }
                   1760: 
                   1761: void execlib_sysinit(void)
                   1762: {
                   1763:     CPTR tmp, tmp2;
                   1764:     CPTR enosys = deftrap(EXEC_ENOSYS);
                   1765:     CPTR intvec = deftrap(EXEC_StandardIntVec);
1.1.1.2 ! root     1766:     CPTR inttrap = deftrap2(EXEC_IntTrap, TRAPFLAG_NORETVAL|TRAPFLAG_NOREGSAVE, "");
1.1       root     1767:     CPTR sysstack;
                   1768:     int i;
                   1769: 
                   1770:     tmp = here();
                   1771:     calltrap2(enosys); dw(RTS);
                   1772:     
                   1773:     /* why 0x400? */
1.1.1.2 ! root     1774:     EXEC_sysbase = 0x400 + NR_EXEC_FUNCTIONS*6;
        !          1775:     memset(raddr(EXEC_sysbase), 0, 558);
        !          1776:     put_long(4, EXEC_sysbase);
1.1       root     1777: 
                   1778:     /* Build vectors. We initialize SetFunction so we can call execlib_Init() */
                   1779:     tmp2 = here();
                   1780:     calltrap(deftrap(execl_SetFunction));
                   1781:     dw(RTS);
                   1782:     for (i = 0; i < NR_EXEC_FUNCTIONS; i++) {
1.1.1.2 ! root     1783:        put_word(EXEC_sysbase - 6*(i+1), 0x4EF9);
        !          1784:        put_long(EXEC_sysbase - 6*(i+1) + 2, i == 69 ? tmp2 : tmp);
1.1       root     1785:     }
                   1786: 
                   1787:     /* Build syslists */
1.1.1.2 ! root     1788:     EXEC_NewList(EXEC_sysbase + 322); /* MemList */
        !          1789:     EXEC_NewList(EXEC_sysbase + 336); /* ResourceList */
        !          1790:     EXEC_NewList(EXEC_sysbase + 350); /* ResourceList */
        !          1791:     EXEC_NewList(EXEC_sysbase + 364); /* List */
        !          1792:     EXEC_NewList(EXEC_sysbase + 378); /* LibList */
        !          1793:     EXEC_NewList(EXEC_sysbase + 392); /* PortList */
        !          1794:     EXEC_NewList(EXEC_sysbase + 406); /* TaskReady */
        !          1795:     EXEC_NewList(EXEC_sysbase + 420); /* TaskWait */
        !          1796:     EXEC_NewList(EXEC_sysbase + 434); /* SoftInts[5] */
        !          1797:     EXEC_NewList(EXEC_sysbase + 450); 
        !          1798:     EXEC_NewList(EXEC_sysbase + 466); 
        !          1799:     EXEC_NewList(EXEC_sysbase + 482); 
        !          1800:     EXEC_NewList(EXEC_sysbase + 498); 
        !          1801:     EXEC_NewList(EXEC_sysbase + 532); /* SemaphoreList */
        !          1802: 
        !          1803:     put_long(EXEC_sysbase + 10, ds("exec.library"));
        !          1804:     put_word(EXEC_sysbase + 20, 34); put_word(EXEC_sysbase + 22, 0);
        !          1805:     put_byte(EXEC_sysbase + 8, NT_LIBRARY);
        !          1806:     put_byte(EXEC_sysbase + 9, 0);
        !          1807:     
        !          1808:     put_long(EXEC_sysbase + 42, 0);
        !          1809:     put_long(EXEC_sysbase + 46, 0);
        !          1810:     put_long(EXEC_sysbase + 50, 0);
        !          1811:     put_long(EXEC_sysbase + 62, chipmem_size);
        !          1812:     put_long(EXEC_sysbase + 514, 0xFFFFFFFF);
        !          1813:     put_long(EXEC_sysbase + 518, 0); /* seems to contain random values */
        !          1814:     put_long(EXEC_sysbase + 522, 0);
        !          1815:     put_long(EXEC_sysbase + 526, 0);
        !          1816:     put_word(EXEC_sysbase + 530, 0x3232);
        !          1817:     put_long(EXEC_sysbase + 546, 0);
        !          1818:     put_long(EXEC_sysbase + 550, 0);
        !          1819:     put_long(EXEC_sysbase + 554, 0);
        !          1820:     EXEC_Enqueue(EXEC_sysbase + 378, EXEC_sysbase);
        !          1821:     
        !          1822:     tmp = EXEC_sysbase + 558; /* sizeof struct V34 execbase */
1.1       root     1823:     /* We put the supervisor stack at the end, the user stack for our new
                   1824:      * task at the end - 0x800, and build the ResModules array at the bottom
                   1825:      * of the stack */
                   1826:     sysstack = chipmem_size - 0x2000;
                   1827:     
                   1828:     /* Don't mess with Fast or Bogo for now, just set up Chip */
                   1829:     EXEC_AddMemList(sysstack - tmp, MEMF_CHIP|MEMF_PUBLIC, -10, tmp, 
                   1830:                    ds("Chip Memory"));
                   1831: 
                   1832:     /* Set up the CPU */
                   1833:     regs.usp = chipmem_size - 0x800;
                   1834:     regs.isp = chipmem_size; /* What about MSP? */
1.1.1.2 ! root     1835:     m68k_areg(regs, 7) = regs.usp;
1.1       root     1836:     regs.s = 0; regs.m = 0;
                   1837:     regs.vbr = 0;
                   1838:     regs.t0 = regs.t1 = 0;
                   1839:     regs.intmask = 0;
                   1840:     put_word(0xDFF09A, 0x7FFF);
                   1841:     put_word(0xDFF096, 0x7FFF);
                   1842:     put_word(0xDFF09C, 0x7FFF);
                   1843:     put_word(0xDFF09A, 0xC000);
1.1.1.2 ! root     1844:     put_word(0xDFF096, 0x8200);
1.1       root     1845:     /* Initialize our supported functions */
                   1846:     execlib_init();
                   1847:     execlib_init2();
                   1848:     
                   1849:     /* Initialize interrupts */
                   1850:     intr_count = 0; 
1.1.1.2 ! root     1851:     put_byte(EXEC_sysbase + 294, 0xFF);
        !          1852:     put_byte(EXEC_sysbase + 295, 0xFF);
1.1       root     1853: 
                   1854:     tmp = here();
                   1855:     calltrap2(inttrap);
                   1856:     dw(RTE);
                   1857:     for (i = 0; i < 8; i++)
                   1858:        put_long((24+i)*4, tmp);
                   1859:     
                   1860:     tmp = here();
                   1861:     calltrap2(intvec); dw(RTS);
                   1862:     for (i = 0; i < 16; i++) {
                   1863:        tmp2 = 0;
                   1864:        /* Is this a server chain? */
                   1865:        if (i == 3 || i == 4 || i == 5 || i == 13 || i == 15)
                   1866:            EXEC_NewList(tmp2 = EXEC_AllocMem(14, MEMF_PUBLIC));
1.1.1.2 ! root     1867:        put_long(EXEC_sysbase + 84 + i*12, tmp2);
        !          1868:        put_long(EXEC_sysbase + 84 + i*12 + 4, tmp);
        !          1869:        put_long(EXEC_sysbase + 84 + i*12 + 8, 0);
1.1       root     1870:     }
                   1871:     put_word(0xDFF09A, 0xAFC3); /* Enable everything but the server chains */
1.1.1.2 ! root     1872:     
        !          1873:     task_to_kill = NULL;
1.1       root     1874:     /* Set up the init task.  We don't really set it up properly. */
                   1875:     tmp = EXEC_AllocMem(92, MEMF_CLEAR);
1.1.1.2 ! root     1876:     put_long(EXEC_sysbase + 276, tmp);
        !          1877:     put_byte(tmp + 8, NT_TASK);
1.1       root     1878:     put_byte(tmp + 9, -127);
                   1879:     put_long(tmp + 10, ds("init"));
                   1880:     put_byte(tmp + 16, 0xFF);
                   1881:     put_byte(tmp + 17, 0xFF);
                   1882:     put_long(tmp + 54, chipmem_size - 0x804);
                   1883:     put_long(tmp + 58, chipmem_size - 0x1800);
                   1884:     put_long(tmp + 62, chipmem_size - 0x800);
                   1885:     put_byte(tmp + 15, TS_RUN);
                   1886:     put_long(tmp + 18,0x0000FFFF);
                   1887:     EXEC_NewList(tmp + 74);
                   1888:     idle_task.next = idle_task.prev = &idle_task;
                   1889:     idle_task.exectask = tmp;
                   1890:     idle_task.stack = NULL; /* we have a stack for this one already */
                   1891: 
                   1892:     /* Set up an idle task */
                   1893:     tmp2 = here();
1.1.1.2 ! root     1894:     dw (0xFF0D); dw (0x4eF9); dl (tmp2);
1.1       root     1895: 
                   1896:     tmp = EXEC_AllocMem(92, MEMF_CLEAR);
1.1.1.2 ! root     1897:     put_byte(tmp + 8, NT_TASK);
1.1       root     1898:     put_byte(tmp + 9, -128);
                   1899:     put_long(tmp + 10, ds("idle"));
1.1.1.2 ! root     1900:     put_byte(tmp + 16, 0xFF);
        !          1901:     put_byte(tmp + 17, 0xFF);
1.1       root     1902:     put_long(tmp + 58, chipmem_size - 0x2000);
                   1903:     put_long(tmp + 62, chipmem_size - 0x1800);
                   1904:     put_long(tmp + 54, chipmem_size - 0x1804);
                   1905:     EXEC_NewList(tmp + 74);
                   1906:     EXEC_AddTask(tmp,  tmp2, 0); /* This won't start executing yet */
1.1.1.2 ! root     1907: /*    find_newtask(tmp)->regs.s = 1;*/
1.1       root     1908: 
                   1909: 
                   1910:     /* Grep Kickstart for resident modules */
1.1.1.2 ! root     1911:     m68k_areg(regs, 7) -= 4;
        !          1912:     put_long(m68k_areg(regs, 7), 0);
        !          1913:     tmp2 = m68k_areg(regs, 7);
1.1       root     1914:     for (tmp = 0xF80000; tmp < 0xFFFFFF; tmp += 2) {
                   1915:        if (get_word(tmp) == 0x4AFC && get_long(tmp + 2) == tmp) {
1.1.1.2 ! root     1916:            m68k_areg(regs, 7) -= 4; put_long(m68k_areg(regs, 7), tmp);
1.1       root     1917:        }
                   1918:     }
1.1.1.2 ! root     1919:     put_long(EXEC_sysbase + 300, m68k_areg(regs, 7));
1.1       root     1920:     /* Bubble me do */
1.1.1.2 ! root     1921:     for (tmp = m68k_areg(regs, 7); tmp < tmp2; tmp += 4) {
1.1       root     1922:        CPTR tmp3;
                   1923:        for (tmp3 = tmp2 - 4; tmp3 > tmp; tmp3 -= 4) {
                   1924:            if ((BYTE)get_byte(get_long(tmp3) + 13) > (BYTE)get_byte(get_long(tmp3 - 4) + 13)) {
                   1925:                CPTR tmp4 = get_long(tmp3);
                   1926:                put_long(tmp3, get_long(tmp3 - 4));
                   1927:                put_long(tmp3 - 4, tmp4);
                   1928:            }
                   1929:        }
                   1930:     }
                   1931:     
1.1.1.2 ! root     1932:     need_resched = quantum_elapsed = 0;
        !          1933: 
1.1       root     1934:     /* Initialize them and watch everything blow up. */
1.1.1.2 ! root     1935:     for (tmp = m68k_areg(regs, 7); (tmp2 = get_long(tmp)) != 0; tmp += 4) {
1.1       root     1936:        UBYTE flags = get_byte(tmp2 + 10);
                   1937:        if (!(flags & 1)) /* RTF_COLDSTART? */
                   1938:            continue;
1.1.1.2 ! root     1939:        fprintf(stderr, "Initializing %s\n", raddr(get_long(tmp2 + 18)));
        !          1940: /*     if (strcmp("timer.device", raddr(get_long(tmp2 + 14))) == 0) {
        !          1941:            timerdev_init();
        !          1942:            continue;
        !          1943:        }*/
        !          1944:        m68k_areg(regs, 6) = EXEC_sysbase;
1.1       root     1945:        EXEC_InitResident(tmp2, /* ? */ 0);
1.1.1.2 ! root     1946: 
1.1       root     1947:     }
                   1948:     /* Idle task */
                   1949:     for(;;) {
                   1950:        Call68k(0xF0FFF0 - 4, 0);
                   1951:        schedule();
                   1952:     }
                   1953: }
                   1954: 
                   1955: /* 
                   1956:  *  Install the gfx-library-replacement 
                   1957:  */
                   1958: void execlib_install(void)
                   1959: {
                   1960:     ULONG begin, end, resname, resid;
                   1961:     int i;
                   1962:     
                   1963:     if (!use_gfxlib)
                   1964:        return;
                   1965:     
                   1966:     resname = ds("UAEexeclib.resource");
                   1967:     resid = ds("UAE execlib 0.1");
                   1968: 
                   1969:     begin = here();
                   1970:     dw(0x4AFC);             /* RTC_MATCHWORD */
                   1971:     dl(begin);              /* our start address */
                   1972:     dl(0);                  /* Continue scan here */
                   1973:     dw(0x0101);             /* RTF_COLDSTART; Version 1 */
                   1974:     dw(0x0805);             /* NT_RESOURCE; pri 5 */
                   1975:     dl(resname);            /* name */
                   1976:     dl(resid);              /* ID */
                   1977:     dl(here() + 4);         /* Init area: directly after this */
                   1978: 
                   1979:     calltrap(deftrap(execlib_init)); dw(RTS);
                   1980: 
                   1981:     end = here();
                   1982:     org(begin + 6);
                   1983:     dl(end);
                   1984: 
                   1985:     org(end);
                   1986: 
                   1987:     intr_count = 1; /* So we don't try to schedule if we don't emulate
                   1988:                     * all of Exec */
                   1989: }
1.1.1.2 ! root     1990: #else
        !          1991: ULONG EXEC_Forbid(void) { return 0; }
        !          1992: ULONG EXEC_Permit(void) { return 0; }
        !          1993: ULONG EXEC_Enable(void) { return 0; }
        !          1994: ULONG EXEC_Disable(void) { return 0; }
        !          1995: void execlib_install (void) { abort (); }
        !          1996: #endif

unix.superglobalmegacorp.com

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