--- SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp 2005/03/05 18:33:30 1.59 +++ SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp 2005/07/03 22:02:01 1.65 @@ -183,36 +183,42 @@ public: void operator delete(void *p); }; -// Memory allocator returning areas aligned on 16-byte boundaries +// Memory allocator returning sheepshaver_cpu objects aligned on 16-byte boundaries +// FORMAT: [ alignment ] magic identifier, offset to malloc'ed data, sheepshaver_cpu data void *sheepshaver_cpu::operator new(size_t size) { - void *p; + const int ALIGN = 16; -#if defined(HAVE_POSIX_MEMALIGN) - if (posix_memalign(&p, 16, size) != 0) + // Allocate enough space for sheepshaver_cpu data + signature + align pad + uint8 *ptr = (uint8 *)malloc(size + ALIGN * 2); + if (ptr == NULL) throw std::bad_alloc(); -#elif defined(HAVE_MEMALIGN) - p = memalign(16, size); -#elif defined(HAVE_VALLOC) - p = valloc(size); // page-aligned! -#else - /* XXX: handle padding ourselves */ - p = malloc(size); -#endif - return p; + // Align memory + int ofs = 0; + while ((((uintptr)ptr) % ALIGN) != 0) + ofs++, ptr++; + + // Insert signature and offset + struct aligned_block_t { + uint32 pad[(ALIGN - 8) / 4]; + uint32 signature; + uint32 offset; + uint8 data[sizeof(sheepshaver_cpu)]; + }; + aligned_block_t *blk = (aligned_block_t *)ptr; + blk->signature = FOURCC('S','C','P','U'); + blk->offset = ofs + (&blk->data[0] - (uint8 *)blk); + assert((((uintptr)&blk->data) % ALIGN) == 0); + return &blk->data[0]; } void sheepshaver_cpu::operator delete(void *p) { -#if defined(HAVE_MEMALIGN) || defined(HAVE_VALLOC) -#if defined(__GLIBC__) - // this is known to work only with GNU libc - free(p); -#endif -#else - free(p); -#endif + uint32 *blk = (uint32 *)p; + assert(blk[-2] == FOURCC('S','C','P','U')); + void *ptr = (void *)(((uintptr)p) - blk[-1]); + free(ptr); } sheepshaver_cpu::sheepshaver_cpu() @@ -263,7 +269,7 @@ void sheepshaver_cpu::execute_emul_op(ui for (int i = 0; i < 7; i++) r68.a[i] = gpr(16 + i); r68.a[7] = gpr(1); - uint32 saved_cr = get_cr() & CR_field<2>::mask(); + uint32 saved_cr = get_cr() & 0xff9fffff; // mask_operand::compute(11, 8) uint32 saved_xer = get_xer(); EmulOp(&r68, gpr(24), emul_op); set_cr(saved_cr); @@ -796,9 +802,9 @@ sigsegv_return_t sigsegv_handler(sigsegv #error "FIXME: You don't have the capability to skip instruction within signal handlers" #endif - printf("SIGSEGV\n"); - printf(" pc %p\n", fault_instruction); - printf(" ea %p\n", fault_address); + fprintf(stderr, "SIGSEGV\n"); + fprintf(stderr, " pc %p\n", fault_instruction); + fprintf(stderr, " ea %p\n", fault_address); dump_registers(); ppc_cpu->dump_log(); enter_mon(); @@ -909,6 +915,7 @@ void emul_ppc(uint32 entry) void TriggerInterrupt(void) { + idle_resume(); #if 0 WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1); #else @@ -929,13 +936,7 @@ void HandleInterrupt(powerpc_registers * if (int32(ReadMacInt32(XLM_IRQ_NEST)) > 0) return; - // Do nothing if there is no pending interrupt - if (InterruptFlags == 0) - return; - - // Current interrupt nest level - static int interrupt_depth = 0; - ++interrupt_depth; + // Update interrupt count #if EMUL_TIME_STATS interrupt_count++; #endif @@ -951,7 +952,7 @@ void HandleInterrupt(powerpc_registers * #if INTERRUPTS_IN_NATIVE_MODE case MODE_NATIVE: // 68k emulator inactive, in nanokernel? - if (r->gpr[1] != KernelDataAddr && interrupt_depth == 1) { + if (r->gpr[1] != KernelDataAddr) { // Prepare for 68k interrupt level 1 WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1); @@ -1009,9 +1010,6 @@ void HandleInterrupt(powerpc_registers * break; #endif } - - // We are done with this interrupt - --interrupt_depth; } static void get_resource(void); @@ -1041,6 +1039,18 @@ void sheepshaver_cpu::execute_native_op( case NATIVE_VIDEO_DO_DRIVER_IO: gpr(3) = (int32)(int16)VideoDoDriverIO(gpr(3), gpr(4), gpr(5), gpr(6), gpr(7)); break; + case NATIVE_ETHER_AO_GET_HWADDR: + AO_get_ethernet_address(gpr(3)); + break; + case NATIVE_ETHER_AO_ADD_MULTI: + AO_enable_multicast(gpr(3)); + break; + case NATIVE_ETHER_AO_DEL_MULTI: + AO_disable_multicast(gpr(3)); + break; + case NATIVE_ETHER_AO_SEND_PACKET: + AO_transmit_packet(gpr(3)); + break; case NATIVE_ETHER_IRQ: EtherIRQ(); break;