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

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: #undef USE_EXECLIB
                     10: 
                     11: #include "sysconfig.h"
                     12: #include "sysdeps.h"
                     13: 
                     14: #include <assert.h>
                     15: #include <signal.h>
                     16: #ifdef USE_EXECLIB
                     17: #include <setjmp.h>
                     18: #endif
                     19: 
                     20: #include "config.h"
                     21: #include "options.h"
                     22: #include "memory.h"
                     23: #include "custom.h"
                     24: #include "newcpu.h"
                     25: #include "xwin.h"
                     26: #include "autoconf.h"
                     27: #include "osemu.h"
                     28: 
                     29: static CPTR sysbase;
                     30: 
                     31: /*
                     32:  * Exec list management
                     33:  */
                     34: 
                     35: void EXEC_NewList(CPTR list)
                     36: {
                     37:     put_long(list, list + 4);
                     38:     put_long(list + 4, 0);
                     39:     put_long(list + 8, list);
                     40: }
                     41: 
                     42: void EXEC_Insert(CPTR list, CPTR node, CPTR pred)
                     43: {
                     44:     CPTR succ;
                     45:     if (pred == 0)
                     46:        pred = list;
                     47:     put_long(node, succ = get_long(pred));
                     48:     put_long(pred, node);
                     49:     put_long(succ + 4, node);
                     50:     put_long(node + 4, pred);
                     51: }
                     52: 
                     53: void EXEC_Enqueue(CPTR list, CPTR node)
                     54: {
                     55:     int pri = (BYTE)get_byte (node + 9);
                     56:     CPTR lnode = get_long(list); /* lh_Head */
                     57:     CPTR prev = 0, next;
                     58:     
                     59:     for (;(next = get_long(lnode)) != 0 && (BYTE)get_byte(lnode + 9) >= pri;) {
                     60:        prev = lnode;
                     61:        lnode = next;
                     62:     }
                     63:     EXEC_Insert(list, node, prev);
                     64: }
                     65: 
                     66: void EXEC_Remove(CPTR node)
                     67: {
                     68:     CPTR pred = get_long(node + 4), succ = get_long(node);
                     69:     put_long(pred, succ);
                     70:     put_long(succ + 4, pred);
                     71: }
                     72: 
                     73: ULONG EXEC_RemHead(CPTR list)
                     74: {
                     75:     CPTR head = get_long(list);
                     76:     if (get_long(head) == 0)
                     77:        return 0;
                     78:     EXEC_Remove(head);
                     79:     return head;
                     80: }
                     81: 
                     82: ULONG EXEC_RemTail(CPTR list)
                     83: {
                     84:     CPTR tail = get_long(list + 8);
                     85:     if (get_long(tail + 4) == 0)
                     86:        return 0;
                     87:     
                     88:     EXEC_Remove(tail);
                     89:     return tail;
                     90: }
                     91: 
                     92: void EXEC_AddTail(CPTR list, CPTR node) 
                     93: {
                     94:     EXEC_Insert(list, node, get_long(list + 8)); 
                     95: }
                     96: 
                     97: CPTR EXEC_FindName(CPTR start, char *name)
                     98: {
                     99:     CPTR node = start;
                    100:     if (name == NULL)
                    101:        return 0;
                    102:     
                    103:     for (;;) {
                    104:        CPTR nnp;
                    105:        char *nn;
                    106: 
                    107:        node = get_long(start);
                    108: 
                    109:        if (node == 0)
                    110:            break;
                    111:        nnp = get_long(node + 10);
                    112:        if (nnp != 0 && (nn = get_real_address(nnp)) != NULL)
                    113:            if (strcmp(nn, name) == 0)
                    114:                return node;
                    115:        start = node;
                    116:     }
                    117:     return 0;
                    118: }
                    119: 
                    120: static ULONG execl_Enqueue(void) { EXEC_Enqueue(regs.a[0], regs.a[1]); return 0; }
                    121: static ULONG execl_Insert(void) { EXEC_Insert(regs.a[0], regs.a[1], regs.a[2]); return 0; }
                    122: static ULONG execl_AddHead(void) { EXEC_Insert(regs.a[0], regs.a[1], 0); return 0; }
                    123: static ULONG execl_AddTail(void) { EXEC_Insert(regs.a[0], regs.a[1], get_long(regs.a[0] + 8)); return 0; }
                    124: static ULONG execl_Remove(void) { EXEC_Remove(regs.a[1]); return 0; }
                    125: static ULONG execl_RemHead(void) { return EXEC_RemHead(regs.a[0]); }
                    126: static ULONG execl_RemTail(void) { return EXEC_RemTail(regs.a[0]); }
                    127: static ULONG execl_FindName(void) { CPTR n = EXEC_FindName(regs.a[0], get_real_address(regs.a[1])); ZFLG = n == 0; return n; }
                    128: 
                    129: /*
                    130:  * Miscellaneous
                    131:  */
                    132: 
                    133: void EXEC_InitStruct(CPTR inittable, CPTR memory, unsigned long size)
                    134: {
                    135:     CPTR dptr = memory;
                    136:     UBYTE *mem = get_real_address(memory);
                    137:     if (memory == 0 || mem == NULL || !valid_address(memory, size)) {
                    138:        fprintf(stderr, "Foo\n");
                    139:        return;
                    140:     }
                    141:     memset(mem, 0, size);
                    142:     fprintf(stderr, "InitStruct\n");
                    143:     for (;;) {
                    144:        UBYTE command;
                    145:        int count, desttype, srcloc;
                    146:        ULONG offset;
                    147: 
                    148:        /* Read commands from even bytes */
                    149:        inittable = (inittable + 1) & ~1;
                    150: 
                    151:        command = get_byte(inittable);
                    152:        if (command == 0)
                    153:            break;
                    154:        desttype = (command >> 6) & 3;
                    155:        srcloc = (command >> 4) & 3;
                    156:        count = (command & 15) + 1;
                    157: 
                    158:        if (desttype == 3) {
                    159:            dptr = memory + (get_long(inittable) & 0xFFFFFF);
                    160:            inittable += 4;
                    161:        } else if (desttype == 2) {
                    162:            dptr = memory + get_byte(inittable+1), inittable += 2;
                    163:        } else 
                    164:            inittable++;
                    165: 
                    166:        if (srcloc != 0)
                    167:            inittable = (inittable + 1) & ~1;
                    168: 
                    169:        if (desttype != 1) {
                    170:            for(; count > 0; count--) {
                    171:                switch (srcloc) {
                    172:                 case 0: put_long(dptr, get_long(inittable)); dptr += 4; inittable += 4; break;
                    173:                 case 1: put_word(dptr, get_word(inittable)); dptr += 2; inittable += 2; break;
                    174:                 case 2: put_byte(dptr, get_byte(inittable)); dptr += 1; inittable += 1; break;
                    175:                }
                    176:            }
                    177:        } else {
                    178:            ULONG data;
                    179:            switch (srcloc) {
                    180:             case 0: data = get_byte(inittable); inittable += 1; break;
                    181:             case 1: data = get_word(inittable); inittable += 2; break;
                    182:             case 2: data = get_long(inittable); inittable += 4; break;
                    183:             default: data = 0; /* Alert */ break;
                    184:            }
                    185:            for(; count > 0; count--) {
                    186:                switch (srcloc) {
                    187:                 case 0: put_long(dptr, data); dptr += 4; break;
                    188:                 case 1: put_word(dptr, data); dptr += 2; break;
                    189:                 case 2: put_byte(dptr, data); dptr += 1; break;
                    190:                }
                    191:            }
                    192:        }
                    193:     }
                    194: }
                    195: /* The size parameter sometimes seems to contain garbage in the top 16 bit */
                    196: static ULONG execl_InitStruct(void) { EXEC_InitStruct(regs.a[1], regs.a[2], regs.d[0] & 0xFFFF); return 0; }
                    197: 
                    198: /*
                    199:  * Interrupts
                    200:  * This is all very confusing. As I see things, the IntVects field of the
                    201:  * ExecBase is set up as follows:
                    202:  *   One interrupt may either be assigned an IntServer, or an IntHandler.
                    203:  *   PORTS, COPER, VERTB EXTER and NMI are set up as Servers (at least that's
                    204:  *   what the AutoDocs say), the others as IntHandlers.
                    205:  *   An IntServer field has a pointer to an Exec list in the iv_Data field,
                    206:  *   the list contains all the server Interrupt nodes in a nice chain. The
                    207:  *   iv_Node field is zero. For an IntHandler, the iv_Node field contains a
                    208:  *   pointer to the node that was passed in SetIntVector.
                    209:  */
                    210: 
                    211: CPTR EXEC_SetIntVector(int number, CPTR interrupt)
                    212: {
                    213:     CPTR oldvec = get_long(sysbase + 84 + 12*number + 8);
                    214:     if (interrupt == 0) {
                    215:        put_long(sysbase + 84 + 12*number, 0);
                    216:        put_long(sysbase + 84 + 12*number + 4, 0);
                    217:        put_long(sysbase + 84 + 12*number + 8, 0);
                    218:     } else {
                    219:        put_long(sysbase + 84 + 12*number, get_long(interrupt + 14));
                    220:        put_long(sysbase + 84 + 12*number + 4, get_long(interrupt + 18));
                    221:        put_long(sysbase + 84 + 12*number + 8, interrupt);
                    222:     }
                    223:     return oldvec;
                    224: }
                    225: 
                    226: void EXEC_RemIntServer(ULONG nr, CPTR interrupt)
                    227: {
                    228:     CPTR list = get_long(sysbase + 84 + nr*12);
                    229:     
                    230:     EXEC_Remove(interrupt);
                    231:     /* Disable interrupt if necessary */
                    232:     if (get_long(get_long(list)) == 0)
                    233:        put_word(0xDFF09A, 1 << nr);
                    234: }
                    235: 
                    236: void EXEC_AddIntServer(ULONG nr, CPTR interrupt)
                    237: {
                    238:     CPTR list = get_long(sysbase + 84 + nr*12);
                    239:     int was_empty;
                    240: 
                    241:     /* Disable interrupt if necessary */
                    242:     was_empty = get_long(get_long(list)) == 0;
                    243:     
                    244:     EXEC_Enqueue(list, interrupt);
                    245:     if (was_empty)
                    246:        put_word(0xDFF09A, 0x8000 | (1 << nr));
                    247:     
                    248: }
                    249: 
                    250: static ULONG execl_SetIntVector(void) { return EXEC_SetIntVector(regs.d[0], regs.a[1]); }
                    251: static ULONG execl_AddIntServer(void) { EXEC_AddIntServer(regs.d[0] & 15, regs.a[1]); return 0; }
                    252: static ULONG execl_RemIntServer(void) { EXEC_RemIntServer(regs.d[0] & 15, regs.a[1]); return 0; }
                    253: 
                    254: /*
                    255:  * Memory functions
                    256:  */
                    257: 
                    258: #define MEMF_PUBLIC 1
                    259: #define MEMF_CHIP 2
                    260: #define MEMF_FAST 4
                    261: #define MEMF_LOCAL 256
                    262: #define MEMF_24BITDMA 512
                    263: #define MEMF_CLEAR (1<<16)
                    264: #define MEMF_LARGEST (1<<17)
                    265: #define MEMF_REVERSE (1<<18)
                    266: #define MEMF_TOTAL (1<<19)
                    267: 
                    268: CPTR EXEC_Allocate(CPTR memheader, unsigned long size)
                    269: {
                    270:     CPTR chunk, chunkpp;
                    271:     unsigned long avail;
                    272:     
                    273:     size = (size + 7) & ~7;
                    274:     
                    275:     if (size == 0 || size > get_long(memheader + 28))
                    276:        return 0;
                    277:        
                    278:     for (chunk = get_long(chunkpp = memheader + 16); chunk != 0; chunkpp = chunk, chunk = get_long(chunk))
                    279:        if ((avail = get_long(chunk + 4)) >= size) {
                    280:            CPTR nextchunk = get_long(chunk);
                    281:            if (avail-size == 0)
                    282:                put_long(chunkpp, nextchunk);
                    283:            else {
                    284:                put_long(chunkpp, chunk + size);
                    285:                put_long(chunk + size, nextchunk);
                    286:                put_long(chunk + size + 4, avail - size);
                    287:            }
                    288:            put_long(memheader + 28, get_long(memheader + 28) - size);
                    289:            return chunk;
                    290:        }
                    291:     return 0;
                    292: }
                    293: 
                    294: void EXEC_Deallocate(CPTR memheader, CPTR addr, unsigned long size)
                    295: {
                    296:     CPTR chunk, chunkpp;
                    297:     CPTR areaend;
                    298: 
                    299:     if (addr == 0)
                    300:        return;
                    301: 
                    302:     size = (size + 7) & ~7;
                    303:     areaend = addr + size;
                    304:     
                    305:     put_long(memheader + 28, get_long(memheader + 28) + size);
                    306:     
                    307:     for (chunk = get_long(chunkpp = memheader + 16); chunk != 0; chunkpp = chunk, chunk = get_long(chunk)) {
                    308:        if (chunk + get_long(chunk + 4) == addr) {
                    309:            /* Merge with this and go ahead so we can also merge with the next */
                    310:            put_long(chunkpp, get_long(chunk));
                    311:            addr = chunk; size += get_long(chunk + 4);
                    312:            chunk = chunkpp;
                    313:            continue;
                    314:        }
                    315:        if (areaend == chunk) {
                    316:            /* Merge with previous */
                    317:            put_long(chunkpp, addr);
                    318:            put_long(addr, get_long(chunk));
                    319:            put_long(addr + 4, get_long(chunk + 4) + size);
                    320:            return;
                    321:        }
                    322:        if (chunk > addr)
                    323:            break;
                    324:     }
                    325:     put_long(chunkpp, addr);
                    326:     put_long(addr, chunk);
                    327:     put_long(addr + 4, size);
                    328: }
                    329: 
                    330: CPTR EXEC_AllocMem(unsigned long size, ULONG requirements)
                    331: {
                    332:     CPTR nextmh,  memheader = get_long(sysbase + 322);
                    333:     ULONG attrs = requirements & (MEMF_PUBLIC | MEMF_CHIP | MEMF_FAST);
                    334:     CPTR result = 0;
                    335: 
                    336:     size = (size + 7) & ~7;
                    337: 
                    338:     for (;(nextmh = get_long(memheader)) != 0; memheader = nextmh) {
                    339:        if ((get_word(memheader + 14) & attrs) != attrs)
                    340:            continue;
                    341:        result = EXEC_Allocate(memheader, size);
                    342:        if (result != 0)
                    343:            break;
                    344:     }
                    345:     if (result) {
                    346:        if (requirements & MEMF_CLEAR)
                    347:            memset(get_real_address(result), 0, size);
                    348:     }
                    349:     return result;
                    350: }
                    351: 
                    352: CPTR EXEC_AllocEntry(CPTR ml)
                    353: {
                    354:     CPTR newml = EXEC_AllocMem(16 + 8*get_word(ml + 14), MEMF_PUBLIC|MEMF_CLEAR);
                    355:     int i;
                    356: 
                    357:     if (newml == 0)
                    358:        return 0x80000000|MEMF_PUBLIC;
                    359:     for (i = 0; i < get_word(ml + 14); i++) {
                    360:        ULONG reqs = get_long(ml + 16 + 8*i);
                    361:        ULONG addr = EXEC_AllocMem(get_long(ml + 16 + 8*i + 4), reqs);
                    362:        if (addr == 0)
                    363:            /* Thank god for SetPatch */
                    364:            return 0x80000000 | reqs;
                    365:        put_long(newml + 16 + 8*i, addr);
                    366:        put_long(newml + 16 + 8*i + 4, reqs);
                    367:     }
                    368:     return newml;
                    369: }
                    370: 
                    371: void EXEC_FreeMem(CPTR addr, unsigned long size)
                    372: {
                    373:     CPTR nextmh,  memheader = get_long(sysbase + 322);
                    374: 
                    375:     size = (size + 7) & ~7;
                    376:     if (addr == 0)
                    377:        return;
                    378: 
                    379:     for (;(nextmh = get_long(memheader)) != 0; memheader = nextmh) {
                    380:        if (get_long(memheader + 20) <= addr
                    381:            && get_long(memheader + 24) > addr) {
                    382:            EXEC_Deallocate(memheader, addr, size);
                    383:            return;
                    384:        }
                    385:     }
                    386: }
                    387: 
                    388: unsigned long EXEC_AvailMem(ULONG requirements)
                    389: {
                    390:     ULONG attrs = requirements & (MEMF_PUBLIC | MEMF_CHIP | MEMF_FAST);
                    391:     CPTR nextmh, memheader = get_long(sysbase + 322);
                    392:     CPTR result = 0;
                    393: 
                    394:     for (;(nextmh = get_long(memheader)) != 0; memheader = nextmh) {
                    395:        if ((get_word(memheader + 14) & attrs) != attrs)
                    396:            continue;
                    397:        if (attrs & MEMF_LARGEST) {
                    398:            unsigned long maxsize = 0;
                    399:            CPTR chunk;
                    400:            for (chunk = get_long(memheader + 16); chunk != 0; chunk = get_long(chunk))
                    401:                if (get_long(chunk+4) > maxsize)
                    402:                    maxsize = get_long(chunk + 4);
                    403:            result += maxsize;
                    404:        } else if (attrs & MEMF_TOTAL) {
                    405:            result += get_long(memheader + 24) - get_long(memheader + 20);
                    406:        } else result += get_long(memheader + 28);
                    407:     }
                    408:     return result;
                    409: }
                    410: 
                    411: void EXEC_AddMemList(unsigned long size, ULONG attrs, int pri, CPTR base,
                    412:                     CPTR name)
                    413: {
                    414:     put_byte(base + 8, 0);
                    415:     put_byte(base + 9, pri);
                    416:     put_long(base + 10, name);
                    417:     put_word(base + 14, attrs);
                    418:     put_long(base + 16, base + 32);
                    419:     put_long(base + 20, base + 32);
                    420:     put_long(base + 36, size - 32);
                    421:     put_long(base + 28, size - 32);
                    422:     put_long(base + 24, base + size);
                    423:     EXEC_Enqueue(sysbase + 322, base);
                    424: }
                    425: 
                    426: static ULONG execl_AddMemList(void)
                    427: {
                    428:     EXEC_AddMemList(regs.d[0], regs.d[1], (LONG)regs.d[2], regs.a[0], regs.a[1]);
                    429:     return 0;
                    430: }
                    431: 
                    432: static ULONG execl_CopyMem(void)
                    433: {
                    434:     UBYTE *src = get_real_address(regs.a[0]);
                    435:     UBYTE *dst = get_real_address(regs.a[1]);
                    436: 
                    437:     if (src != NULL && dst != NULL
                    438:        && valid_address(regs.a[0], regs.d[0])
                    439:        && valid_address(regs.a[1], regs.d[0]))
                    440:        memcpy(dst, src, regs.d[0]);
                    441:     else
                    442:        fprintf(stderr, "CopyMem with bogus parameters\n");
                    443:     return 0;
                    444: }
                    445: 
                    446: static ULONG execl_AllocMem(void) { return EXEC_AllocMem(regs.d[0], regs.d[1]); }
                    447: static ULONG execl_AllocEntry(void) { return EXEC_AllocEntry(regs.a[0]); }
                    448: static ULONG execl_Allocate(void) { return EXEC_Allocate(regs.a[0], regs.d[0]); }
                    449: static ULONG execl_FreeMem(void) { EXEC_FreeMem(regs.a[1], regs.d[0]); return 0; }
                    450: static ULONG execl_AvailMem(void) { return EXEC_AvailMem(regs.d[1]); }
                    451: static ULONG execl_Deallocate(void) { EXEC_Deallocate(regs.a[0], regs.a[1], regs.d[0]); return 0; }
                    452: 
                    453: /*
                    454:  * Scheduling
                    455:  */
                    456: 
                    457: #define TS_RUN 2
                    458: #define TS_READY 3
                    459: #define TS_WAIT 4
                    460: #define TS_EXCEPT 5
                    461: 
                    462: struct NewTask {
                    463:     struct NewTask *next, *prev;
                    464:     CPTR exectask;
                    465: #ifdef USE_EXECLIB
                    466:     jmp_buf j;
                    467: #endif
                    468:     void *stack;
                    469:     struct regstruct regs;
                    470:     struct flag_struct flags;
                    471: };
                    472: 
                    473: static struct NewTask idle_task;
                    474: static int intr_count, need_resched;
                    475: 
                    476: static struct NewTask *find_newtask(CPTR task)
                    477: {
                    478:     /* Ugh, this is ugly */
                    479:     struct NewTask *t = &idle_task;
                    480:     do {
                    481:        if (t->exectask == task)
                    482:            return t;
                    483:        t = t->next;
                    484:     } while (t != &idle_task);
                    485:     fprintf(stderr, "Uh oh. Task list corrupt\n");
                    486: }
                    487: 
                    488: static void schedule(void)
                    489: {
                    490: #ifdef USE_EXECLIB
                    491:     CPTR readylist = sysbase + 406;
                    492:     CPTR readytask = get_long(readylist);
                    493:     CPTR runtask = get_long(sysbase + 276);
                    494:     struct NewTask *runtask_nt, *readytask_nt;
                    495:     unsigned long oldflags;
                    496: 
                    497:     int idis;
                    498:     
                    499:     need_resched = 0;
                    500:     /* Any ready tasks? */
                    501:     if (get_long(readytask) == 0)
                    502:        return;
                    503:     
                    504:     /* If the running task is going to sleep, don't check priorities*/
                    505:     if (get_byte(runtask + 15) != TS_WAIT) {
                    506:        /* Has the running task a higher priority than any ready tasks? */
                    507:        if ((BYTE)get_byte(runtask + 9) > (BYTE)get_byte(readytask + 9))
                    508:        return;
                    509:        /* We should only preempt a task of the same priority if the quantum
                    510:         * has expired. Hmmm... */
                    511:     }
                    512:     if (get_byte(runtask + 15) == TS_RUN)
                    513:        put_byte(runtask + 15, TS_READY);
                    514:     if (get_byte(runtask + 15) == TS_WAIT)
                    515:        EXEC_Enqueue(sysbase + 420, runtask);
                    516:     else
                    517:        EXEC_Enqueue(readylist, runtask);
                    518:     put_byte(readytask + 15, TS_RUN);
                    519:     EXEC_Remove(readytask);
                    520:     
                    521:     readytask_nt = find_newtask(readytask);
                    522:     runtask_nt = find_newtask(runtask);
                    523:     
                    524: 
                    525:     oldflags = regs.spcflags;
                    526:     runtask_nt->regs = regs;
                    527:     runtask_nt->flags = regflags;
                    528:     regs = readytask_nt->regs;
                    529:     regflags = readytask_nt->flags;
                    530:     regs.spcflags = (regs.spcflags & ~PRESERVED_FLAGS) | (oldflags & PRESERVED_FLAGS);
                    531:     
                    532:     put_byte(runtask + 16, get_byte(sysbase + 294));
                    533:     put_byte(runtask + 17, get_byte(sysbase + 295));
                    534:     put_byte(sysbase + 294, idis = get_byte(readytask + 16));
                    535:     put_byte(sysbase + 295, get_byte(readytask + 17));
                    536:     put_long(sysbase + 276, readytask);
                    537:     /* Set INTENA according to new interrupt enable status */
                    538:     if (idis == 0xFF)
                    539:        put_word(0xDFF09A, 0xC000);
                    540:     else
                    541:        put_word(0xDFF09A, 0x4000);
                    542:     /* Whee... */
                    543:     fprintf(stderr, "Task switch: new task %s\n", get_real_address(get_long(readytask + 10)));
                    544:     if (setjmp(runtask_nt->j) == 0)
                    545:        longjmp(readytask_nt->j, 1);
                    546:     regs.spcflags &= ~SPCFLAG_BRK;
                    547: #endif
                    548: }
                    549: 
                    550: static __inline__ void maybe_schedule(void)
                    551: {
                    552:     /* @@@ Should we avoid a schedule when supervisor bit is set?
                    553:      * Definitely not if the running task is the idle task */
                    554:     if (intr_count == 0 && get_byte(sysbase + 294) == 0xFF && get_byte(sysbase + 295) == 0xFF && need_resched)
                    555:        schedule();
                    556: }
                    557: 
                    558: /*
                    559:  * Signals
                    560:  */
                    561: 
                    562: int EXEC_AllocSignal(int signum)
                    563: {
                    564:     CPTR thistask = get_long(sysbase + 276);
                    565:     ULONG sigalloc = get_long(thistask + 18);
                    566:     if (signum == -1)
                    567:        for (signum = 0; signum < 32; signum++)
                    568:            if ((sigalloc & (1 << signum)) == 0)
                    569:                break;
                    570:     
                    571:     if ((sigalloc & (1 << signum)) == 0) {
                    572:        put_long(thistask + 18, sigalloc | (1 << signum));
                    573:     } else
                    574:        signum = -1;
                    575: 
                    576:     return signum;
                    577: }
                    578: 
                    579: void EXEC_FreeSignal(int signum)
                    580: {
                    581:     CPTR thistask = get_long(sysbase + 276);
                    582:     if (signum != -1)
                    583:        return;
                    584:     put_long(thistask + 18, get_long(thistask + 18) & ~(1 << signum));
                    585: }
                    586: 
                    587: ULONG EXEC_SetSignal(ULONG newsig, ULONG exec_sigmask)
                    588: {
                    589:     CPTR task = get_long(sysbase + 276);
                    590:     ULONG signals = get_long(task + 26);
                    591:     /* @@@ check SigExcept here */
                    592:     put_long(task + 26, (signals & ~exec_sigmask) | (newsig & exec_sigmask));
                    593:     return signals;
                    594: }
                    595: 
                    596: void EXEC_Signal(CPTR task, ULONG exec_sigmask)
                    597: {
                    598:     ULONG exec_sigs = get_long(task + 26);
                    599:     ULONG sigwait = get_long(task + 22);
                    600:     put_long(task + 26, exec_sigs | exec_sigmask);
                    601:     if (get_byte(task + 15) == TS_WAIT && (sigwait & exec_sigmask) != 0) {
                    602:        EXEC_Remove(task);
                    603:        EXEC_Enqueue(sysbase + 406, task);
                    604:        need_resched = 1;
                    605:        maybe_schedule();
                    606:     }
                    607: }
                    608: 
                    609: ULONG EXEC_Wait(ULONG exec_sigmask)
                    610: {
                    611:     CPTR task = get_long(sysbase + 276);
                    612:     ULONG exec_sigs = get_long(task + 26);
                    613:     if ((exec_sigs & exec_sigmask) != 0) {
                    614:        put_long(task + 26, exec_sigs & ~exec_sigmask);
                    615:        return exec_sigs & exec_sigmask;
                    616:     }
                    617:     if (get_byte(sysbase + 294) != 0xFF || get_byte(sysbase + 295) != 0xFF)
                    618:     {
                    619:        fprintf(stderr, "Arrgh, task Wait()ing when it shouldn't\n");
                    620:     }
                    621:     if (intr_count || regs.s) {
                    622:        fprintf(stderr, "Arrgh, task Wait()ing when it _really_ shouldn't\n");
                    623:     }
                    624: 
                    625:     put_byte(task + 15, TS_WAIT);
                    626:     put_long(task + 22, exec_sigmask);
                    627:     schedule();
                    628:     exec_sigs = get_long(task + 26);
                    629:     if ((exec_sigs & exec_sigmask) != 0) {
                    630:        put_long(task + 26, exec_sigs & ~exec_sigmask);
                    631:        return exec_sigs & exec_sigmask;
                    632:     } 
                    633:     fprintf(stderr, "Bug: task woke up without signals\n");
                    634:     return 0;
                    635: }
                    636: 
                    637: static ULONG execl_SetSignal(void) { return EXEC_SetSignal(regs.d[0], regs.d[1]); }
                    638: static ULONG execl_Signal(void) { EXEC_Signal(regs.a[1], regs.d[0]); return 0; }
                    639: static ULONG execl_Wait(void) { return EXEC_Wait(regs.d[0]); }
                    640: static ULONG execl_AllocSignal(void) { return EXEC_AllocSignal((BYTE)regs.d[0]); }
                    641: static ULONG execl_FreeSignal(void) { EXEC_FreeSignal((BYTE)regs.d[0]); return 0; }
                    642: 
                    643: /*
                    644:  * Semaphores
                    645:  */
                    646: 
                    647: void EXEC_InitSemaphore(CPTR exec_sigsem)
                    648: {
                    649:     EXEC_NewList(exec_sigsem + 16);
                    650:     put_word(exec_sigsem + 14, 0);
                    651:     put_word(exec_sigsem + 44, 0xFFFF);
                    652: }
                    653: 
                    654: ULONG EXEC_AttemptSemaphore(CPTR exec_sigsem)
                    655: {
                    656:     CPTR task = get_long(sysbase + 276);
                    657:     UWORD count = get_word(exec_sigsem + 44);
                    658:     if (count == 0xFFFF) {
                    659:        /* Semaphore free -> lock it */
                    660:        put_word(exec_sigsem + 44, 0);
                    661:        put_long(exec_sigsem + 40, task);
                    662:        put_word(exec_sigsem + 14, 1);
                    663:        return 1;
                    664:     }
                    665:     if (get_long(exec_sigsem + 40) == task) {
                    666:        /* Locked by same task -> Increment NestCount */
                    667:        put_word(exec_sigsem + 14, get_word(exec_sigsem + 14) + 1);
                    668:        return 1;
                    669:     }
                    670:     return 0;
                    671: }
                    672: 
                    673: void EXEC_ObtainSemaphore(CPTR exec_sigsem)
                    674: {
                    675:     CPTR task = get_long(sysbase + 276);
                    676:     UWORD count = get_word(exec_sigsem + 44);
                    677:     if (count == 0xFFFF) {
                    678:        /* Semaphore free -> lock it */
                    679:        put_word(exec_sigsem + 44, 0);
                    680:        put_long(exec_sigsem + 40, task);
                    681:        put_word(exec_sigsem + 14, 1);
                    682:        return;
                    683:     }
                    684:     if (get_long(exec_sigsem + 40) == task) {
                    685:        /* Locked by same task -> Increment NestCount */
                    686:        put_word(exec_sigsem + 14, get_word(exec_sigsem + 14) + 1);
                    687:        return;
                    688:     }
                    689:     /* Need to wait. */
                    690:     /* @@@ None of the predefined signals in exec/tasks.h seem to be used
                    691:      * for this. We use 0x8000, which appears not to be used otherwise */
                    692:     put_word(exec_sigsem + 44, count + 1);
                    693:     EXEC_AddTail(exec_sigsem + 16, task);
                    694:     if (EXEC_Wait(0x8000) != 0x8000)
                    695:        fprintf(stderr, "BUG\n");
                    696: 
                    697:     /* Now it's mine, all mine! */
                    698:     put_long(exec_sigsem + 40, task);
                    699:     put_word(exec_sigsem + 14, 1);
                    700: }
                    701: 
                    702: void EXEC_ReleaseSemaphore(CPTR exec_sigsem)
                    703: {
                    704:     UWORD nest = get_word(exec_sigsem + 14);
                    705:     put_word(exec_sigsem + 14, nest - 1);
                    706:     if (nest == 1) {
                    707:        /* We're losing it. Signal the first task on the wait queue
                    708:         * (that one will in turn wake the next, etc.) */
                    709:        CPTR task = EXEC_RemHead(exec_sigsem + 16);
                    710:        UWORD count = get_word(exec_sigsem + 44);
                    711:        put_word(exec_sigsem + 44, count - 1);
                    712:        if (task) {
                    713:            EXEC_Signal(task, 0x8000);
                    714:        }
                    715:     }
                    716: }
                    717: 
                    718: static ULONG execl_ObtainSemaphore(void) { EXEC_ObtainSemaphore(regs.a[0]); return 0; }
                    719: static ULONG execl_ReleaseSemaphore(void) { EXEC_ReleaseSemaphore(regs.a[0]); return 0; }
                    720: static ULONG execl_FindSemaphore(void) { return EXEC_FindName(sysbase + 532, get_real_address(regs.a[1])); }
                    721: static ULONG execl_InitSemaphore(void) { EXEC_InitSemaphore(regs.a[0]); return 0; }
                    722: static ULONG execl_AttemptSemaphore(void) { return EXEC_AttemptSemaphore(regs.a[0]); }
                    723: static ULONG execl_AddSemaphore(void) { put_byte(regs.a[1] + 8, 15); EXEC_Enqueue(sysbase + 532, regs.a[1]); return 0; }
                    724: 
                    725: /*
                    726:  * Messages and ports
                    727:  */
                    728: 
                    729: CPTR EXEC_GetMsg(CPTR port)
                    730: {
                    731:     return EXEC_RemHead(port + 20);
                    732: }
                    733: 
                    734: /* This is shared between PutMsg and ReplyMsg */
                    735: static void EXEC_doputmsg(CPTR port, CPTR msg)
                    736: {
                    737:     UBYTE flags = get_byte (port + 14);
                    738:     EXEC_AddTail(port + 20, msg);
                    739:     if (flags == 0)
                    740:        EXEC_Signal(get_long(port + 16), 1 << get_byte(port + 15));
                    741:     else if (flags == 1)
                    742:        fprintf(stderr, "PA_SOFTINT unsupported\n");
                    743:     
                    744: }
                    745: 
                    746: void EXEC_PutMsg(CPTR port, CPTR msg)
                    747: {
                    748:     put_byte(msg + 8, 5);
                    749:     EXEC_doputmsg(port, msg);
                    750: }
                    751: 
                    752: void EXEC_ReplyMsg(CPTR msg)
                    753: {    
                    754:     put_byte(msg + 8, 7);
                    755:     EXEC_doputmsg(get_long(msg + 14), msg);
                    756: }
                    757: 
                    758: CPTR EXEC_WaitPort(CPTR port)
                    759: {
                    760:     for (;;) {
                    761:        CPTR msg = get_long(port + 20);
                    762:        if (get_long(msg) != 0)
                    763:            return msg;
                    764:        if (get_byte(port + 14) != 0)
                    765:            fprintf(stderr, "Don't know how to WaitPort()\n");
                    766:        EXEC_Wait(1 << get_byte(port + 15));
                    767:     }
                    768: }
                    769: 
                    770: static ULONG execl_GetMsg(void) { return EXEC_GetMsg(regs.a[0]); }
                    771: static ULONG execl_PutMsg(void) { EXEC_PutMsg(regs.a[0], regs.a[1]); return 0; }
                    772: static ULONG execl_ReplyMsg(void) { EXEC_ReplyMsg(regs.a[1]); return 0; }
                    773: static ULONG execl_WaitPort(void) { return EXEC_WaitPort(regs.a[0]); }
                    774: static ULONG execl_FindPort(void) { return EXEC_FindName(sysbase + 392, get_real_address(regs.a[1])); }
                    775: static ULONG execl_AddPort(void) { put_byte(regs.a[1] + 8, 4); EXEC_Enqueue(sysbase + 392, regs.a[1]); return 0; }
                    776: 
                    777: /*
                    778:  * I/O
                    779:  */
                    780: 
                    781: LONG EXEC_WaitIO(CPTR ioreq)
                    782: {
                    783:     /* The device is supposed to clear the IO_QUICK bit if it's going to
                    784:      * reply to the command */
                    785:     if ((get_byte(ioreq + 30) & 1) == 1)
                    786:        return (LONG)(BYTE)get_byte(ioreq + 31);
                    787: 
                    788:     for (;;) {
                    789:        if (get_byte(ioreq + 8) == 7) /* NT_REPLYMSG? */
                    790:            break;
                    791:        /* We'll just hope that this a) has a ReplyPort and b) that port
                    792:         * is of type PA_SIGNAL 
                    793:         * Don't WaitPort() here: WaitPort() returns a message, and we
                    794:         * aren't sure it's for us. */
                    795:        
                    796:        EXEC_Wait(1 << get_byte(get_long(ioreq + 14) + 15));
                    797:     }
                    798:     EXEC_Remove(ioreq);
                    799:     return (LONG)(BYTE)get_byte(ioreq + 31);
                    800: }
                    801: 
                    802: static void EXEC_BeginIO(CPTR ioreq)
                    803: {
                    804:     CPTR dev = get_long(ioreq + 20);
                    805:     regs.a[6] = dev;
                    806:     regs.a[1] = ioreq;
                    807:     Call68k(dev - 30, 1);
                    808: }
                    809: 
                    810: void EXEC_DoIO(CPTR ioreq)
                    811: {
                    812:     put_byte(ioreq + 30, 1);
                    813:     EXEC_BeginIO(ioreq);
                    814:     EXEC_WaitIO(ioreq);
                    815: }
                    816:     
                    817: void EXEC_SendIO(CPTR ioreq)
                    818: {
                    819:     put_byte(ioreq + 30, 0);
                    820:     EXEC_BeginIO(ioreq);
                    821: }
                    822: 
                    823: CPTR EXEC_CheckIO(CPTR ioreq)
                    824: {
                    825:     if ((get_byte(ioreq + 30) & 1) == 1)
                    826:        return ioreq;
                    827:     if (get_byte(ioreq + 8) == 7)
                    828:        return ioreq;
                    829:     return 0;
                    830: }
                    831: 
                    832: static ULONG execl_WaitIO(void) { return EXEC_WaitIO(regs.a[1]); }
                    833: static ULONG execl_DoIO(void) { EXEC_DoIO(regs.a[1]); return 0;  }
                    834: static ULONG execl_SendIO(void) { EXEC_SendIO(regs.a[1]); return 0;  }
                    835: static ULONG execl_CheckIO(void) { return EXEC_CheckIO(regs.a[1]); }
                    836: 
                    837: /*
                    838:  * Libraries
                    839:  */
                    840: 
                    841: void EXEC_SumLibrary(CPTR lib)
                    842: {
                    843:     CPTR start = lib - get_word(lib + 16);
                    844:     int len = get_word(lib + 16) + get_word(lib + 18);
                    845:     ULONG sum = 0;
                    846:     UWORD flags = get_word(lib + 14);
                    847:     
                    848:     if (flags & 1) /* SUMMING? */
                    849:        return;
                    850:     if (!(flags & 4)) /* SUMUSED? */
                    851:        return;
                    852:     put_word(lib + 14, flags & ~2); /* mark as not changed */
                    853:     /* Pretend the checksum is OK, I don't care enough */
                    854: }
                    855: 
                    856: CPTR EXEC_SetFunction(CPTR lib, int funcOffset, CPTR function)
                    857: {
                    858:     CPTR oldfunc = get_long(lib + funcOffset + 2);
                    859:     put_word(lib + funcOffset, 0x4EF9);
                    860:     put_long(lib + funcOffset + 2, function);
                    861:     put_word(lib + 14, get_word(lib + 14) | 2);
                    862:     EXEC_SumLibrary(lib);
                    863:     return oldfunc;
                    864: }
                    865: 
                    866: void EXEC_AddLibrary(CPTR lib)
                    867: {
                    868:     EXEC_Enqueue(sysbase + 378, lib);
                    869:     put_word(lib + 14, 2); /* mark as changed */
                    870:     EXEC_SumLibrary(lib);
                    871: }
                    872: 
                    873: CPTR EXEC_OpenLibrary(char *name, int version)
                    874: {
                    875:     CPTR lib = EXEC_FindName(sysbase + 378, name);
                    876:     if (lib != 0) {
                    877:        regs.a[6] = lib;
                    878:        regs.d[0] = version;
                    879:        lib = Call68k(lib - 6, 1);
                    880:     }
                    881:     return lib;
                    882: }
                    883: 
                    884: CPTR EXEC_OpenDevice(char *name, ULONG unit, CPTR ioRequest, ULONG flags)
                    885: {
                    886:     CPTR dev = EXEC_FindName(sysbase + 350, name);
                    887:     CPTR replyport = get_long(ioRequest + 14);
                    888:     put_long(ioRequest + 20, dev);
                    889:     put_byte(ioRequest + 31, 0);
                    890:     put_byte(ioRequest + 30, flags); /* is this right? */
                    891:     if (replyport == 0)
                    892:        fprintf(stderr, "ioRequest has no ReplyPort\n");
                    893:     else {
                    894:        CPTR rtask = get_long(replyport + 16);
                    895:        if (rtask == 0)
                    896:            fprintf(stderr, "replyTask == 0\n");
                    897:        else if (rtask != get_long(sysbase + 276))
                    898:            fprintf(stderr, "replyTask != current\n");
                    899: /*     put_long(replyport + 16, get_long(sysbase + 276));*/
                    900:     }
                    901:     if (dev != 0) {
                    902:        regs.a[6] = dev;
                    903:        regs.a[1] = ioRequest;
                    904:        regs.d[0] = unit;
                    905:        regs.d[1] = flags;
                    906:        dev = Call68k(dev - 6, 1);
                    907:     }
                    908:     return (LONG)(BYTE)get_byte(ioRequest + 31);
                    909: }
                    910: 
                    911: void EXEC_AddDevice(CPTR lib)
                    912: {
                    913:     EXEC_Enqueue(sysbase + 350, lib);
                    914: }
                    915: 
                    916: void EXEC_AddResource(CPTR lib)
                    917: {
                    918:     EXEC_Enqueue(sysbase + 336, lib);
                    919: }
                    920: 
                    921: CPTR EXEC_OpenResource(char *name)
                    922: {
                    923:     CPTR lib = EXEC_FindName(sysbase + 336, name);
                    924:     return lib;
                    925: }
                    926: 
                    927: void EXEC_MakeFunctions(CPTR target, CPTR funcarray, CPTR funcdispb)
                    928: {
                    929:     if (funcdispb != 0) {
                    930:        WORD tmp;
                    931:        for (;;) {
                    932:            tmp = get_word(funcarray); funcarray += 2;
                    933:            if (tmp == -1)
                    934:                break;
                    935:            target -= 6;
                    936:            put_word(target, 0x4EF9); /* JMP.L */
                    937:            put_long(target + 2, funcdispb + tmp);
                    938:        }
                    939:     } else {
                    940:        CPTR tmp;
                    941:        for (;;) {
                    942:            tmp = get_long(funcarray); funcarray += 4;
                    943:            if (tmp == (CPTR)-1)
                    944:                break;
                    945:            target -= 6;
                    946:            put_word(target, 0x4EF9); /* JMP.L */
                    947:            put_long(target + 2, tmp);
                    948:        }
                    949:     }
                    950: }
                    951: 
                    952: /* This doesn't work yet */
                    953: CPTR EXEC_MakeLibrary(CPTR vectors, CPTR structure, CPTR init,
                    954:                      unsigned long dsize, ULONG seglist_b)
                    955: {
                    956:     CPTR seglist = seglist_b << 2;
                    957:     int vec_cnt = 0;
                    958:     unsigned long negsize;
                    959:     CPTR base, fdispb = 0, funcarray = vectors;
                    960:     ULONG retval = 0;
                    961: 
                    962:     fprintf(stderr, "MakeLibrary\n");
                    963:     if (get_word (vectors) == (UWORD)-1) {
                    964:        int offs = 2;
                    965:        fdispb = vectors;
                    966:        funcarray += 2;
                    967:        while (get_word (vectors+offs) != (UWORD)-1) {
                    968:            offs += 2;
                    969:            vec_cnt++;
                    970:        }
                    971:     } else {
                    972:        int offs = 0;
                    973:        while (get_long (vectors+offs) != (LONG)-1) {
                    974:            offs += 4; 
                    975:            vec_cnt++;
                    976:        }
                    977:     }
                    978:     negsize = (vec_cnt * 6 + 3) & ~3;
                    979:     dsize = (dsize + 3) & ~3;
                    980: 
                    981:     base = EXEC_AllocMem(negsize + dsize, MEMF_PUBLIC|MEMF_CLEAR);
                    982:     if (base == 0) /* Uh oh */
                    983:        return 0;
                    984:     EXEC_MakeFunctions(base + negsize, funcarray, fdispb);
                    985:     base += negsize;
                    986:     put_word(base + 16, negsize);
                    987:     put_word(base + 18, dsize);
                    988:     if (structure != 0) {
                    989:        /* Size is set to 0 so we won't clear it again */
                    990:        EXEC_InitStruct(structure, base, 0);
                    991:     }
                    992:     if (init != 0) {
                    993:        regs.a[6] = sysbase;
                    994:        regs.a[0] = seglist_b; /* BCPL seglist here? */
                    995:        regs.d[0] = base;
                    996:        /* call it */
                    997:        retval = Call68k(init, 0);
                    998:     } else
                    999:        retval = base;
                   1000:     
                   1001:     return retval;
                   1002: }
                   1003: 
                   1004: CPTR EXEC_InitResident(CPTR resident, ULONG segList)
                   1005: {
                   1006:     UBYTE flags = get_byte(resident + 10);
                   1007:     
                   1008:     if (flags & 0x80) {
                   1009:        CPTR autoinit = get_long(resident + 22);
                   1010:        return EXEC_MakeLibrary(get_long(autoinit + 4), get_long(autoinit + 8),
                   1011:                                get_long(autoinit + 12), get_long(autoinit), segList >> 4);
                   1012:     }
                   1013:     
                   1014:     regs.d[0] = 0; regs.a[0] = segList; regs.a[6] = sysbase;
                   1015:     return Call68k(get_long(resident + 22), 0);
                   1016: }
                   1017: 
                   1018: static ULONG execl_MakeFunctions(void) { EXEC_MakeFunctions(regs.a[0], regs.a[1], regs.a[2]); return 0; }
                   1019: static ULONG execl_SumLibrary(void) { EXEC_SumLibrary(regs.a[1]); return 0; }
                   1020: static ULONG execl_SetFunction(void) { return EXEC_SetFunction(regs.a[1], (WORD)regs.a[0], regs.d[0]); }
                   1021: static ULONG execl_AddLibrary(void) { EXEC_AddLibrary(regs.a[1]); return 0; }
                   1022: static ULONG execl_AddDevice(void) { EXEC_AddDevice(regs.a[1]); return 0; }
                   1023: static ULONG execl_AddResource(void) { EXEC_AddResource(regs.a[1]); return 0; }
                   1024: static ULONG execl_OpenLibrary(void) { return EXEC_OpenLibrary(get_real_address(regs.a[1]), regs.d[0]); }
                   1025: static ULONG execl_OpenDevice(void) { return EXEC_OpenDevice(get_real_address(regs.a[0]), regs.d[0], regs.a[1], regs.d[1]); }
                   1026: static ULONG execl_OpenResource(void) { return EXEC_OpenResource(get_real_address(regs.a[1])); }
                   1027: static ULONG execl_MakeLibrary(void) { return EXEC_MakeLibrary(regs.a[0], regs.a[1], regs.a[2], regs.d[0], regs.d[1]); }
                   1028: 
                   1029: /*
                   1030:  * Tasks
                   1031:  */
                   1032: 
                   1033: static void task_startup(void)
                   1034: {
                   1035:     m68k_setpc(regs.pc);
                   1036:     Call68k_retaddr(regs.pc, 0, get_long(regs.a[7] - 4));
                   1037:     fprintf(stderr, "Task fell through at the end\n");
                   1038: }
                   1039: 
                   1040: CPTR EXEC_AddTask(CPTR task, CPTR initPC, CPTR finalPC)
                   1041: {
                   1042: #ifdef USE_EXECLIB
                   1043:     struct NewTask *nt = (struct NewTask *)malloc(sizeof (struct NewTask));
                   1044:     nt->exectask = task;
                   1045:     nt->prev = &idle_task;
                   1046:     nt->next = idle_task.next;
                   1047:     idle_task.next->prev = nt;
                   1048:     idle_task.next = nt;
                   1049:     memset(&nt->regs, 0, sizeof (nt->regs));
                   1050:     nt->regs.pc = initPC;
                   1051:     nt->regs.a[7] = get_long(task + 54);
                   1052: 
                   1053:     if (finalPC == 0)
                   1054:        finalPC = 0xF0FFF0; /* standard "return from 68k mode" calltrap */
                   1055:     put_byte(task + 16, 0xFF);
                   1056:     put_byte(task + 17, 0xFF);
                   1057:     put_long(nt->regs.a[7] - 4, finalPC);
                   1058:     nt->stack = malloc(65536); /* @@@ make this smaller after checking that
                   1059:                                * no parts of the emulator need much stack
                   1060:                                * space */
                   1061:     nt->j[0].__sp = nt->stack + 65536;
                   1062:     nt->j[0].__pc = &task_startup;
                   1063:     put_byte(task + 15, TS_READY);
                   1064:     put_long(task + 18,0x0000FFFF); /* all tasks have the lower 16 signals allocated */
                   1065:     EXEC_Enqueue(sysbase + 406, task);
                   1066:     need_resched = 1;
                   1067:     maybe_schedule();
                   1068:     return task;
                   1069: #endif
                   1070: }
                   1071: 
                   1072: CPTR EXEC_FindTask(char *name)
                   1073: {
                   1074:     char *n;
                   1075:     CPTR v;
                   1076: 
                   1077:     if (name == NULL || ((n = get_real_address(get_long(get_long(sysbase + 276) + 10))) != NULL
                   1078:                         && strcmp(n, name) == 0))
                   1079:        return get_long(sysbase + 276);
                   1080:     
                   1081:     v = EXEC_FindName(sysbase + 406, name); /* ready tasks */
                   1082:     if (v != 0)
                   1083:        return v;
                   1084:     return EXEC_FindName(sysbase + 420, name); /* waiting tasks */
                   1085: }
                   1086: 
                   1087: static ULONG execl_FindTask(void) { return EXEC_FindTask(regs.a[1] == 0 ? NULL : get_real_address(regs.a[1])); }
                   1088: static ULONG execl_AddTask(void) { return EXEC_AddTask(regs.a[1], regs.a[2], regs.a[3]); }
                   1089: 
                   1090: ULONG EXEC_Forbid(void)
                   1091: {
                   1092:     int count = (BYTE)get_byte(sysbase + 295);
                   1093:     count++;
                   1094:     put_byte(sysbase + 295, count);
                   1095:     return 0; 
                   1096: }
                   1097: ULONG EXEC_Permit(void) 
                   1098: {
                   1099:     int count = (BYTE)get_byte(sysbase + 295);
                   1100:     if (count == -1)
                   1101:        fprintf(stderr, "Too many Permit() calls\n");
                   1102:     else
                   1103:        count--;
                   1104:     put_byte(sysbase + 295, count);    
                   1105:     maybe_schedule();
                   1106:     return 0;
                   1107: }
                   1108: 
                   1109: ULONG EXEC_Disable(void) 
                   1110: {
                   1111:     int count = (BYTE)get_byte(sysbase + 294);
                   1112:     count++;
                   1113:     put_byte(sysbase + 294, count);
                   1114:     put_word(0xDFF09A, 0x4000);
                   1115:     return 0;
                   1116: }
                   1117: 
                   1118: ULONG EXEC_Enable(void)
                   1119: {
                   1120:     int count = (BYTE)get_byte(sysbase + 294);
                   1121:     if (count == -1)
                   1122:        fprintf(stderr, "Too many Enable() calls\n");
                   1123:     else
                   1124:        count--;
                   1125:     if (count == -1)
                   1126:        put_word(0xDFF09A, 0xC000);
                   1127:     put_byte(sysbase + 294, count);
                   1128:     maybe_schedule();
                   1129:     return 0;
                   1130: }
                   1131: /*
                   1132:  *  Initialization
                   1133:  */
                   1134: static ULONG execlib_init(void)
                   1135: {
                   1136:     sysbase = get_long(4);
                   1137:     
                   1138:     /* CopyMem and CopyMemQuick */
                   1139:     libemu_InstallFunction(execl_CopyMem, sysbase, -630);
                   1140:     libemu_InstallFunction(execl_CopyMem, sysbase, -624);
                   1141:     libemu_InstallFunction(execl_Allocate, sysbase, -186);
                   1142:     libemu_InstallFunction(execl_AllocMem, sysbase, -198);
                   1143:     libemu_InstallFunction(execl_Deallocate, sysbase, -192);
                   1144:     libemu_InstallFunction(execl_FreeMem, sysbase, -210);
                   1145:     libemu_InstallFunction(execl_AvailMem, sysbase, -216);
                   1146:     
                   1147:     /* List management */
                   1148:     libemu_InstallFunction(execl_Insert, sysbase, -234);
                   1149:     libemu_InstallFunction(execl_AddHead, sysbase, -240);
                   1150:     libemu_InstallFunction(execl_AddTail, sysbase, -246);
                   1151:     libemu_InstallFunction(execl_Enqueue, sysbase, -270);
                   1152:     libemu_InstallFunction(execl_RemHead, sysbase, -258);
                   1153:     libemu_InstallFunction(execl_RemTail, sysbase, -264);
                   1154:     libemu_InstallFunction(execl_Remove, sysbase, -252);
                   1155:     libemu_InstallFunction(execl_FindName, sysbase, -276);
                   1156:     
                   1157:     /* Signals */
                   1158:     libemu_InstallFunction(execl_AllocSignal, sysbase, -330);
                   1159:     libemu_InstallFunction(execl_FreeSignal, sysbase, -336);
                   1160: 
                   1161:     /* Semaphores */
                   1162:     libemu_InstallFunction(execl_FindSemaphore, sysbase, -594);
                   1163:     libemu_InstallFunction(execl_InitSemaphore, sysbase, -558);
                   1164:     libemu_InstallFunction(execl_AddSemaphore, sysbase, -600);
                   1165: 
                   1166:     /* Messages/Ports */
                   1167:     libemu_InstallFunction(execl_FindPort, sysbase, -390);
                   1168:     libemu_InstallFunction(execl_GetMsg, sysbase, -372);
                   1169: 
                   1170:     /* Libraries */
                   1171:     libemu_InstallFunction(execl_MakeFunctions, sysbase, -90);
                   1172:     libemu_InstallFunction(execl_SumLibrary, sysbase, -426);
                   1173:     libemu_InstallFunction(execl_SetFunction, sysbase, -420);
                   1174:     
                   1175:     /* Tasks */
                   1176:     libemu_InstallFunction(execl_FindTask, sysbase, -294);
                   1177: 
                   1178:     /* Interrupts */
                   1179:     libemu_InstallFunction(execl_SetIntVector, sysbase, -162);
                   1180:     libemu_InstallFunction(execl_AddIntServer, sysbase, -168);
                   1181:     libemu_InstallFunction(execl_RemIntServer, sysbase, -174);
                   1182:     
                   1183:     /* Miscellaneous */
                   1184:     libemu_InstallFunction(execl_InitStruct, sysbase, -78);
                   1185: 
                   1186:     return 0;
                   1187: }
                   1188: 
                   1189: static ULONG execlib_init2(void)
                   1190: {
                   1191:     sysbase = get_long(4);
                   1192:     
                   1193:     libemu_InstallFunction(execl_AllocEntry, sysbase, -222);
                   1194:     
                   1195:     libemu_InstallFunction(execl_AddLibrary, sysbase, -396);
                   1196:     libemu_InstallFunction(execl_AddDevice, sysbase, -432);
                   1197:     libemu_InstallFunction(execl_AddResource, sysbase, -486);
                   1198:     libemu_InstallFunction(execl_OpenLibrary, sysbase, -552);
                   1199:     libemu_InstallFunction(execl_OpenDevice, sysbase, -444);
                   1200:     libemu_InstallFunction(execl_OpenResource, sysbase, -498);
                   1201:     libemu_InstallFunction(execl_MakeLibrary, sysbase, -84);
                   1202: 
                   1203:     libemu_InstallFunctionFlags(EXEC_Disable, sysbase, -120, TRAPFLAG_NORETVAL);
                   1204:     libemu_InstallFunctionFlags(EXEC_Enable, sysbase, -126, TRAPFLAG_NORETVAL);
                   1205:     libemu_InstallFunctionFlags(EXEC_Permit, sysbase, -138, TRAPFLAG_NORETVAL);
                   1206:     libemu_InstallFunctionFlags(EXEC_Forbid, sysbase, -132, TRAPFLAG_NORETVAL);
                   1207:     
                   1208:     libemu_InstallFunction(execl_AddTask, sysbase, -282);
                   1209: 
                   1210:     libemu_InstallFunction(execl_SetSignal, sysbase, -306);
                   1211:     libemu_InstallFunction(execl_Signal, sysbase, -324);
                   1212:     libemu_InstallFunction(execl_Wait, sysbase, -318);
                   1213: 
                   1214:     libemu_InstallFunction(execl_PutMsg, sysbase, -366);
                   1215:     libemu_InstallFunction(execl_ReplyMsg, sysbase, -378);
                   1216:     libemu_InstallFunction(execl_WaitPort, sysbase, -384);
                   1217: 
                   1218:     libemu_InstallFunction(execl_WaitIO, sysbase, -474);
                   1219:     libemu_InstallFunction(execl_DoIO, sysbase, -456);
                   1220:     libemu_InstallFunction(execl_SendIO, sysbase, -462);
                   1221:     libemu_InstallFunction(execl_CheckIO, sysbase, -468);
                   1222:     
                   1223:     libemu_InstallFunctionFlags(execl_ObtainSemaphore, sysbase, -564, TRAPFLAG_NORETVAL);
                   1224:     libemu_InstallFunctionFlags(execl_ReleaseSemaphore, sysbase, -570, TRAPFLAG_NORETVAL);
                   1225:     libemu_InstallFunction(execl_AttemptSemaphore, sysbase, -576);
                   1226: 
                   1227:     return 0;
                   1228: }
                   1229: 
                   1230: /*
                   1231:  * These functions are one day going to bootstrap the emulated Exec
                   1232:  */
                   1233: 
                   1234: #define NR_EXEC_FUNCTIONS 105 /* V34 (1.3) maximum */
                   1235: 
                   1236: static ULONG EXEC_ENOSYS(void)
                   1237: {
                   1238:     fprintf(stderr, "Not a system call\n");
                   1239:     return 0;
                   1240: }
                   1241: 
                   1242: static ULONG EXEC_StandardIntVec(void)
                   1243: {
                   1244:     int num = regs.a[1];
                   1245:     /* Call the IntHandlers */
                   1246:     return 0;
                   1247: }
                   1248: 
                   1249: static ULONG EXEC_IntTrap(void)
                   1250: {
                   1251:     UWORD intsreq = get_word(0xDFF01E) & get_word(0xDFF01C);
                   1252:     int i;
                   1253:     intr_count++;
                   1254:     
                   1255:     for (i = 13; i >= 0; i--) {
                   1256:        if ((intsreq & (1 << i)) != 0) {
                   1257:        /* Is this a server chain? */
                   1258:            if (i == 3 || i == 4 || i == 5 || i == 13 || i == 15) {
                   1259:                CPTR slist = get_long(sysbase + 84 + 12*i);
                   1260:                CPTR snode = get_long(slist);
                   1261:                for (;;) {
                   1262:                    if (get_long(snode) == 0)
                   1263:                        break;
                   1264:                    regs.a[0] = 0xDFF000;
                   1265:                    regs.a[5] = get_long(snode + 18);
                   1266:                    regs.a[1] = get_long(snode + 14);
                   1267:                    Call68k(regs.a[5], 0);
                   1268:                    if (ZFLG == 0)
                   1269:                        break;
                   1270:                    snode = get_long(snode);
                   1271:                }
                   1272:                put_word(0xDFF09C, 1 << i);
                   1273:            } else {
                   1274:                CPTR intnode = get_long(sysbase + 84 + 12*i + 8);
                   1275:                regs.d[1] = intsreq;
                   1276:                regs.a[1] = get_long(intnode + 14);
                   1277:                regs.a[0] = 0xDFF000;
                   1278:                regs.a[5] = get_long(intnode + 18);
                   1279:                regs.a[6] = sysbase;
                   1280:                Call68k(regs.a[5], 0);
                   1281:            }
                   1282:            break;
                   1283:        }
                   1284:     }
                   1285:     if (i < 0)
                   1286:        fprintf(stderr, "So what interrupt am I supposed to serve?\n");
                   1287:     intr_count--;
                   1288:     maybe_schedule();
                   1289: }
                   1290: 
                   1291: void execlib_sysinit(void)
                   1292: {
                   1293:     CPTR tmp, tmp2;
                   1294:     CPTR enosys = deftrap(EXEC_ENOSYS);
                   1295:     CPTR intvec = deftrap(EXEC_StandardIntVec);
                   1296:     CPTR inttrap = deftrap2(EXEC_IntTrap, TRAPFLAG_NORETVAL);
                   1297:     CPTR sysstack;
                   1298:     int i;
                   1299: 
                   1300:     tmp = here();
                   1301:     calltrap2(enosys); dw(RTS);
                   1302:     
                   1303:     /* why 0x400? */
                   1304:     sysbase = 0x400 + NR_EXEC_FUNCTIONS*6;
                   1305:     memset(get_real_address(sysbase), 0, 558);
                   1306:     put_long(4, sysbase);
                   1307: 
                   1308:     /* Build vectors. We initialize SetFunction so we can call execlib_Init() */
                   1309:     tmp2 = here();
                   1310:     calltrap(deftrap(execl_SetFunction));
                   1311:     dw(RTS);
                   1312:     for (i = 0; i < NR_EXEC_FUNCTIONS; i++) {
                   1313:        put_word(sysbase - 6*(i+1), 0x4EF9);
                   1314:        put_long(sysbase - 6*(i+1) + 2, i == 69 ? tmp2 : tmp);
                   1315:     }
                   1316: 
                   1317:     /* Build syslists */
                   1318:     EXEC_NewList(sysbase + 322); /* MemList */
                   1319:     EXEC_NewList(sysbase + 336); /* ResourceList */
                   1320:     EXEC_NewList(sysbase + 350); /* ResourceList */
                   1321:     EXEC_NewList(sysbase + 364); /* List */
                   1322:     EXEC_NewList(sysbase + 378); /* LibList */
                   1323:     EXEC_NewList(sysbase + 392); /* PortList */
                   1324:     EXEC_NewList(sysbase + 406); /* TaskReady */
                   1325:     EXEC_NewList(sysbase + 420); /* TaskWait */
                   1326:     EXEC_NewList(sysbase + 434); /* SoftInts[5] */
                   1327:     EXEC_NewList(sysbase + 450); 
                   1328:     EXEC_NewList(sysbase + 466); 
                   1329:     EXEC_NewList(sysbase + 482); 
                   1330:     EXEC_NewList(sysbase + 498); 
                   1331:     EXEC_NewList(sysbase + 532); /* SemaphoreList */
                   1332: 
                   1333:     tmp = sysbase + 558; /* sizeof struct V34 execbase */
                   1334:     /* We put the supervisor stack at the end, the user stack for our new
                   1335:      * task at the end - 0x800, and build the ResModules array at the bottom
                   1336:      * of the stack */
                   1337:     sysstack = chipmem_size - 0x2000;
                   1338:     
                   1339:     /* Don't mess with Fast or Bogo for now, just set up Chip */
                   1340:     EXEC_AddMemList(sysstack - tmp, MEMF_CHIP|MEMF_PUBLIC, -10, tmp, 
                   1341:                    ds("Chip Memory"));
                   1342: 
                   1343:     /* Set up the CPU */
                   1344:     regs.usp = chipmem_size - 0x800;
                   1345:     regs.isp = chipmem_size; /* What about MSP? */
                   1346:     regs.a[7] = regs.usp;
                   1347:     regs.s = 0; regs.m = 0;
                   1348:     regs.vbr = 0;
                   1349:     regs.t0 = regs.t1 = 0;
                   1350:     regs.intmask = 0;
                   1351:     put_word(0xDFF09A, 0x7FFF);
                   1352:     put_word(0xDFF096, 0x7FFF);
                   1353:     put_word(0xDFF09C, 0x7FFF);
                   1354:     put_word(0xDFF09A, 0xC000);
                   1355:     put_word(0xDFF096, 0xE100);
                   1356:     /* Initialize our supported functions */
                   1357:     execlib_init();
                   1358:     execlib_init2();
                   1359:     
                   1360:     /* Initialize interrupts */
                   1361:     intr_count = 0; 
                   1362:     put_byte(sysbase + 294, 0xFF);
                   1363:     put_byte(sysbase + 295, 0xFF);
                   1364: 
                   1365:     tmp = here();
                   1366:     calltrap2(inttrap);
                   1367:     dw(RTE);
                   1368:     for (i = 0; i < 8; i++)
                   1369:        put_long((24+i)*4, tmp);
                   1370:     
                   1371:     tmp = here();
                   1372:     calltrap2(intvec); dw(RTS);
                   1373:     for (i = 0; i < 16; i++) {
                   1374:        tmp2 = 0;
                   1375:        /* Is this a server chain? */
                   1376:        if (i == 3 || i == 4 || i == 5 || i == 13 || i == 15)
                   1377:            EXEC_NewList(tmp2 = EXEC_AllocMem(14, MEMF_PUBLIC));
                   1378:        put_long(sysbase + 84 + i*12, tmp2);
                   1379:        put_long(sysbase + 84 + i*12 + 4, tmp);
                   1380:        put_long(sysbase + 84 + i*12 + 8, 0);
                   1381:     }
                   1382:     put_word(0xDFF09A, 0xAFC3); /* Enable everything but the server chains */
                   1383:     /* Set up the init task.  We don't really set it up properly. */
                   1384:     tmp = EXEC_AllocMem(92, MEMF_CLEAR);
                   1385:     put_long(sysbase + 276, tmp);
                   1386:     put_byte(tmp + 8, 1);
                   1387:     put_byte(tmp + 9, -127);
                   1388:     put_long(tmp + 10, ds("init"));
                   1389:     put_byte(tmp + 16, 0xFF);
                   1390:     put_byte(tmp + 17, 0xFF);
                   1391:     put_long(tmp + 54, chipmem_size - 0x804);
                   1392:     put_long(tmp + 58, chipmem_size - 0x1800);
                   1393:     put_long(tmp + 62, chipmem_size - 0x800);
                   1394:     put_byte(tmp + 15, TS_RUN);
                   1395:     put_long(tmp + 18,0x0000FFFF);
                   1396:     EXEC_NewList(tmp + 74);
                   1397:     idle_task.next = idle_task.prev = &idle_task;
                   1398:     idle_task.exectask = tmp;
                   1399:     idle_task.stack = NULL; /* we have a stack for this one already */
                   1400: 
                   1401:     /* Set up an idle task */
                   1402:     tmp2 = here();
                   1403:     dw (0x4E72); dw(0x2000); dw (0x4eF9); dl (tmp2);
                   1404: 
                   1405:     tmp = EXEC_AllocMem(92, MEMF_CLEAR);
                   1406:     put_byte(tmp + 8, 1);
                   1407:     put_byte(tmp + 9, -128);
                   1408:     put_long(tmp + 10, ds("idle"));
                   1409:     put_long(tmp + 58, chipmem_size - 0x2000);
                   1410:     put_long(tmp + 62, chipmem_size - 0x1800);
                   1411:     put_long(tmp + 54, chipmem_size - 0x1804);
                   1412:     EXEC_NewList(tmp + 74);
                   1413:     EXEC_AddTask(tmp,  tmp2, 0); /* This won't start executing yet */
                   1414:     find_newtask(tmp)->regs.s = 1;
                   1415: 
                   1416: 
                   1417:     /* Grep Kickstart for resident modules */
                   1418:     regs.a[7] -= 4;
                   1419:     put_long(regs.a[7], 0);
                   1420:     tmp2 = regs.a[7];
                   1421:     for (tmp = 0xF80000; tmp < 0xFFFFFF; tmp += 2) {
                   1422:        if (get_word(tmp) == 0x4AFC && get_long(tmp + 2) == tmp) {
                   1423:            regs.a[7] -= 4; put_long(regs.a[7], tmp);
                   1424:        }
                   1425:     }
                   1426:     put_long(sysbase + 300, regs.a[7]);
                   1427:     /* Bubble me do */
                   1428:     for (tmp = regs.a[7]; tmp < tmp2; tmp += 4) {
                   1429:        CPTR tmp3;
                   1430:        for (tmp3 = tmp2 - 4; tmp3 > tmp; tmp3 -= 4) {
                   1431:            if ((BYTE)get_byte(get_long(tmp3) + 13) > (BYTE)get_byte(get_long(tmp3 - 4) + 13)) {
                   1432:                CPTR tmp4 = get_long(tmp3);
                   1433:                put_long(tmp3, get_long(tmp3 - 4));
                   1434:                put_long(tmp3 - 4, tmp4);
                   1435:            }
                   1436:        }
                   1437:     }
                   1438:     
                   1439:     /* Initialize them and watch everything blow up. */
                   1440:     for (tmp = regs.a[7]; (tmp2 = get_long(tmp)) != 0; tmp += 4) {
                   1441:        UBYTE flags = get_byte(tmp2 + 10);
                   1442:        if (!(flags & 1)) /* RTF_COLDSTART? */
                   1443:            continue;
                   1444:        if (strncmp("alert", get_real_address(get_long(tmp2 + 18)), 5) == 0)
                   1445:            /*continue*/;
                   1446:        fprintf(stderr, "Initializing %s\n", get_real_address(get_long(tmp2 + 18)));
                   1447:        EXEC_InitResident(tmp2, /* ? */ 0);
                   1448:     }
                   1449:     /* Idle task */
                   1450:     for(;;) {
                   1451:        Call68k(0xF0FFF0 - 4, 0);
                   1452:        schedule();
                   1453:     }
                   1454: }
                   1455: 
                   1456: /* 
                   1457:  *  Install the gfx-library-replacement 
                   1458:  */
                   1459: void execlib_install(void)
                   1460: {
                   1461:     ULONG begin, end, resname, resid;
                   1462:     int i;
                   1463:     
                   1464:     if (!use_gfxlib)
                   1465:        return;
                   1466:     
                   1467:     resname = ds("UAEexeclib.resource");
                   1468:     resid = ds("UAE execlib 0.1");
                   1469: 
                   1470:     begin = here();
                   1471:     dw(0x4AFC);             /* RTC_MATCHWORD */
                   1472:     dl(begin);              /* our start address */
                   1473:     dl(0);                  /* Continue scan here */
                   1474:     dw(0x0101);             /* RTF_COLDSTART; Version 1 */
                   1475:     dw(0x0805);             /* NT_RESOURCE; pri 5 */
                   1476:     dl(resname);            /* name */
                   1477:     dl(resid);              /* ID */
                   1478:     dl(here() + 4);         /* Init area: directly after this */
                   1479: 
                   1480:     calltrap(deftrap(execlib_init)); dw(RTS);
                   1481: 
                   1482:     end = here();
                   1483:     org(begin + 6);
                   1484:     dl(end);
                   1485: 
                   1486:     org(end);
                   1487: 
                   1488:     intr_count = 1; /* So we don't try to schedule if we don't emulate
                   1489:                     * all of Exec */
                   1490: }

unix.superglobalmegacorp.com

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