|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.