Ejemplo n.º 1
0
// print a disassembly starting from addr
void debug_disassemble(unsigned int addr)
{
	char s[160] = { 0 };
	int line = 0;
	const char *name = NULL;

	// print this many lines because that's how many our console can show at a time
	while (line < 13)
	{
		name = g_game->get_address_name(addr); // check to see if this address has a name
		// if so, it's a label name, so print it
		if (name)
		{
			outstr(name);
			printline(":");
			line++;
		}
		sprintf(s, "%04x: ", addr);
		outstr(s);

		addr += get_cpu_struct(g_which_cpu)->dasm_callback(s, addr);

		printline(s);
		line++;
	}

}
Ejemplo n.º 2
0
static inline void
acpi_cstate_halt(void)
{
	cpu_ent *cpu = get_cpu_struct();
	if (cpu->invoke_scheduler)
		return;
	asm("hlt");
}
Ejemplo n.º 3
0
static inline void
acpi_cstate_ffh_enter(CpuidleCstate *cState)
{
	cpu_ent *cpu = get_cpu_struct();
	if (cpu->invoke_scheduler)
		return;

	x86_monitor((void *)&cpu->invoke_scheduler, 0, 0);
	if (!cpu->invoke_scheduler)
		x86_mwait((unsigned long)cState->pData, 1);
}
Ejemplo n.º 4
0
static void
acpi_cstate_quirks(acpi_cpuidle_driver_info *device)
{
	cpu_ent *cpu = get_cpu_struct();
	// Calculated Model Value: M = (Extended Model << 4) + Model
	uint32 model = (cpu->arch.extended_model << 4) + cpu->arch.model;

	// On all recent Intel platforms, ARB_DIS is not necessary
	if (cpu->arch.vendor != VENDOR_INTEL)
		return;
	if (cpu->arch.family > 0xf || (cpu->arch.family == 6 && model >= 0xf))
		device->flags &= ~ACPI_FLAG_C_ARB;
}
Ejemplo n.º 5
0
// I called this MAME_Debug so that I could test mame cpu cores with daphne (obviously I can't ship mame cpu cores with
// daphne due to licensing issues)
void MAME_Debug(void)
{	
	// if we are in trace mode OR if we've got our desired breakpoint
	if (g_cpu_trace || (g_break && (get_cpu_struct(g_which_cpu)->getpc_callback() == g_breakpoint)))
	{
		// if the active cpu is the one to be debugged
		if (cpu_getactivecpu() == g_which_cpu)
		{
			// since we may be at the debug prompt for a long time, we pause the cpu timer here
			cpu_pause();
			debug_prompt();	// give them a prompt
			cpu_unpause();
		}
	}
}
Ejemplo n.º 6
0
// prints cpu registers and flags (keep it on 2 lines)
void print_cpu_context()
{

	char tmpstr[160] = { 0 };
	char nextinstr[160];
	cpudef *cpu = get_cpu_struct(g_which_cpu);
	const char *s = NULL;	// results returned by CPU ascii callback
	int reg = CPU_INFO_REG;	// base register
	int x = 0;	// our X position so we can apply word wrap

	// fill nextinstr with the disassembly of the next instruction
	cpu->dasm_callback(nextinstr, cpu->getpc_callback());

	// print all registers we can
	for (reg = CPU_INFO_REG; reg < MAX_REGS; reg++)
	{
		s = cpu->ascii_info_callback(NULL, reg);

		// if we got something back ...
		if (s[0] != 0)
		{
			outstr(s);
			outstr(" ");	// spacer after register info
			x += strlen(s) + 1;	// +1 because we take into account space

			// if it's time to do a line feed ...
			if (x > 76)
			{
				newline();
				x = 0;
			}
		}
	};
	newline();

	sprintf(tmpstr,
	    "AT PC: [%02X - %s]   FLAGS: [%s] ",
		cpu->getpc_callback(),
		nextinstr,
		cpu->ascii_info_callback(NULL, CPU_INFO_FLAGS)
	);
	printline(tmpstr);
}
Ejemplo n.º 7
0
void debug_prompt()
{
	char s[81] = { 0 };
	UINT8 done = 0;
	struct cpudef *cpu = get_cpu_struct(g_which_cpu);
	unsigned int addr = cpu->getpc_callback();	// this function relies on addr being initialized to PC
	
	g_break = 0;	// once they get  here, don't break anymore
	
	// they have to issue a proper command to get out of the prompt
	while (!done && !get_quitflag())
	{
		newline();
		print_cpu_context();	// show registers and stuff
		
		sprintf(s, "[#%u][%04x Command,'?']-> ", g_which_cpu, cpu->getpc_callback());
		outstr(s);
		con_getline(s, 80);
		switch(toupper(s[0]))
		{
		case 'S':
			// this might help with debugging *shrug*
			g_ldp->pre_step_forward();
			printline("Stepping forward one frame...");
			break;
		case 'C':	// continue execution
			g_cpu_trace = 0;
			done = 1;
			break;
		case 'D':	// disassemble

			// if they entered in an address to disassemble at ...
			if (strlen(s) > 1)
			{
				addr = (unsigned int) strtol(&s[1], NULL, 16);	// convert base 16 text to a number
			}
			// else if they entered no parameters, disassemble from PC

			debug_disassemble(addr);
			break;
		case 'F':	// display current laserdisc frame
			g_ldp->print_frame_info();
			print_ldv1000_info();
			break;
		case 'I':	// break at end of interrupt
			printline("This feature not implemented yet =]");
			break;
		case '=':	// set a new breakpoint
			// if they entered in an address to disassemble at ...
			if (strlen(s) > 1)
			{
				g_breakpoint = (UINT32) strtol(&s[1], NULL, 16);	// convert base 16 text to a number
				g_break = 1;
				g_cpu_trace = 0;
				done = 1;
			}
			// else if they entered no parameters, disassemble from PC
			else
			{
				printline("You must specify an address to break at.");
			}
			break;
		case 'M':	// memory dump
			if (strlen(s) > 1)
			{
				addr = (unsigned int) strtol(&s[1], NULL, 16);
			}
			print_memory_dump(addr);
			break;
		case 'N':	// next CPU
			g_which_cpu++;
			
			// if we've run out of CPU's to debug, wrap back around to the first cpu
			if (get_cpu_struct(g_which_cpu) == NULL) g_which_cpu = 0;
			break;
		case 0:	// carriage return
			g_cpu_trace = 1;
			done = 1;
			break;
		case 'Q':	// quit emulator
			set_quitflag();
			break;
		case 'W':	// write byte at address
			if (strlen(s) > 1)
			{
				int i = 2;	// skip the W and the first whitespace
				Uint32 addr = 0;
				Uint8 val = 0;

				// find next whitespace
				while (s[i] != ' ')
				{
					i++;
				}
				s[i] = 0;	// terminate string so we can do a strtol
				addr = (Uint32) strtol(&s[1], NULL, 16);	// convert base 16 text to a number
				val = (Uint8) strtol(&s[i+1], NULL, 16);	// i+1 because we skip the NULL-terminator we added before

				g_game->cpu_mem_write((Uint16) addr, val);	// assume 16-bit for now
			}
			break;
		case '?':	// get menu
			debug_menu();
			break;
		default:
			printline("Unknown command, press ? to get a menu");
			break;
		}
	} // end while
}
Ejemplo n.º 8
0
/*!	Actually process an interrupt via the handlers registered for that
	vector (IRQ).
*/
int
int_io_interrupt_handler(int vector, bool levelTriggered)
{
    int status = B_UNHANDLED_INTERRUPT;
    struct io_handler* io;
    bool handled = false;

    bigtime_t start = system_time();

    // exceptions and syscalls have their own handlers
    ASSERT(sVectors[vector].type != INTERRUPT_TYPE_EXCEPTION
           && sVectors[vector].type != INTERRUPT_TYPE_SYSCALL);

    if (!sVectors[vector].no_lock_vector)
        acquire_spinlock(&sVectors[vector].vector_lock);

#if !DEBUG_INTERRUPTS
    // The list can be empty at this place
    if (sVectors[vector].handler_list == NULL) {
        dprintf("unhandled io interrupt %d\n", vector);
        if (!sVectors[vector].no_lock_vector)
            release_spinlock(&sVectors[vector].vector_lock);
        return B_UNHANDLED_INTERRUPT;
    }
#endif

    // For level-triggered interrupts, we actually handle the return
    // value (ie. B_HANDLED_INTERRUPT) to decide whether or not we
    // want to call another interrupt handler.
    // For edge-triggered interrupts, however, we always need to call
    // all handlers, as multiple interrupts cannot be identified. We
    // still make sure the return code of this function will issue
    // whatever the driver thought would be useful.

    for (io = sVectors[vector].handler_list; io != NULL; io = io->next) {
        status = io->func(io->data);

#if DEBUG_INTERRUPTS
        if (status != B_UNHANDLED_INTERRUPT)
            io->handled_count++;
#endif
        if (levelTriggered && status != B_UNHANDLED_INTERRUPT)
            break;

        if (status == B_HANDLED_INTERRUPT || status == B_INVOKE_SCHEDULER)
            handled = true;
    }

#if DEBUG_INTERRUPTS
    sVectors[vector].trigger_count++;
    if (status != B_UNHANDLED_INTERRUPT || handled) {
        sVectors[vector].handled_count++;
    } else {
        sVectors[vector].unhandled_count++;
        sVectors[vector].ignored_count++;
    }

    if (sVectors[vector].trigger_count > 10000) {
        if (sVectors[vector].ignored_count > 9900) {
            struct io_handler *last = sVectors[vector].handler_list;
            while (last && last->next)
                last = last->next;

            if (last != NULL && last->no_handled_info) {
                // we have an interrupt handler installed that does not
                // know whether or not it has actually handled the interrupt,
                // so this unhandled count is inaccurate and we can't just
                // disable
            } else {
                if (sVectors[vector].handler_list == NULL
                        || sVectors[vector].handler_list->next == NULL) {
                    // this interrupt vector is not shared, disable it
                    sVectors[vector].enable_count = -100;
                    arch_int_disable_io_interrupt(vector);
                    dprintf("Disabling unhandled io interrupt %d\n", vector);
                } else {
                    // this is a shared interrupt vector, we cannot just disable it
                    dprintf("More than 99%% interrupts of vector %d are unhandled\n",
                            vector);
                }
            }
        }

        sVectors[vector].trigger_count = 0;
        sVectors[vector].ignored_count = 0;
    }
#endif

    if (!sVectors[vector].no_lock_vector)
        release_spinlock(&sVectors[vector].vector_lock);

    SpinLocker vectorLocker(sVectors[vector].load_lock);
    bigtime_t deltaTime = system_time() - start;
    sVectors[vector].last_measure_active += deltaTime;
    vectorLocker.Unlock();

    cpu_ent* cpu = get_cpu_struct();
    if (sVectors[vector].type == INTERRUPT_TYPE_IRQ
            || sVectors[vector].type == INTERRUPT_TYPE_ICI
            || sVectors[vector].type == INTERRUPT_TYPE_LOCAL_IRQ) {
        cpu->interrupt_time += deltaTime;
        if (sVectors[vector].type == INTERRUPT_TYPE_IRQ)
            cpu->irq_time += deltaTime;
    }

    update_int_load(vector);

    if (levelTriggered)
        return status;

    // edge triggered return value

    if (handled)
        return B_HANDLED_INTERRUPT;

    return B_UNHANDLED_INTERRUPT;
}
Ejemplo n.º 9
0
static status_t
acpi_cstate_add(acpi_object_type *object, CpuidleCstate *cState)
{
	acpi_cstate_info *ci = (acpi_cstate_info *)malloc(sizeof(acpi_cstate_info));
	if (!ci)
		return B_NO_MEMORY;

	if (object->object_type != ACPI_TYPE_PACKAGE) {
		dprintf("invalid _CST object\n");
		return B_ERROR;
	}

	if (object->data.package.count != 4) {
		dprintf("invalid _CST number\n");
		return B_ERROR;
	}

	// type
	acpi_object_type * pointer = &object->data.package.objects[1];
	if (pointer->object_type != ACPI_TYPE_INTEGER) {
		dprintf("invalid _CST elem type\n");
		return B_ERROR;
	}
	uint32 n = pointer->data.integer;
	if (n < 1 || n > 3) {
		dprintf("invalid _CST elem value\n");
		return B_ERROR;
	}
	ci->type = n;
	dprintf("C%" B_PRId32 "\n", n);
	snprintf(cState->name, sizeof(cState->name), "C%" B_PRId32, n);

	// Latency
	pointer = &object->data.package.objects[2];
	if (pointer->object_type != ACPI_TYPE_INTEGER) {
		dprintf("invalid _CST elem type\n");
		return B_ERROR;
	}
	n = pointer->data.integer;
	cState->latency = n;
	dprintf("Latency: %" B_PRId32 "\n", n);

	// power
	pointer = &object->data.package.objects[3];
	if (pointer->object_type != ACPI_TYPE_INTEGER) {
		dprintf("invalid _CST elem type\n");
		return B_ERROR;
	}
	n = pointer->data.integer;
	dprintf("power: %" B_PRId32 "\n", n);

	// register
	pointer = &object->data.package.objects[0];
	if (pointer->object_type != ACPI_TYPE_BUFFER) {
		dprintf("invalid _CST elem type\n");
		return B_ERROR;
	}
	if (pointer->data.buffer.length < 15) {
		dprintf("invalid _CST elem length\n");
		return B_ERROR;
	}

	struct acpicpu_reg *reg = (struct acpicpu_reg *)pointer->data.buffer.buffer;
	switch (reg->reg_spaceid) {
		case ACPI_ADR_SPACE_SYSTEM_IO:
			dprintf("IO method\n");
			if (reg->reg_addr == 0) {
				dprintf("illegal address\n");
				return B_ERROR;
			}
			if (reg->reg_bitwidth != 8) {
				dprintf("invalid source length\n");
				return B_ERROR;
			}
			ci->address = reg->reg_addr;
			ci->method = ACPI_CSTATE_SYSIO;
			break;
		case ACPI_ADR_SPACE_FIXED_HARDWARE:
		{
			dprintf("FFH method\n");
			ci->method = ACPI_CSTATE_FFH;
			ci->address = reg->reg_addr;

			// skip checking BM_STS if ACPI_PDC_GAS_BM is cleared
			cpu_ent *cpu = get_cpu_struct();
			if ((cpu->arch.vendor == VENDOR_INTEL) &&
				!(reg->reg_accesssize & ACPI_PDC_GAS_BM))
				ci->skip_bm_sts = 1;
			break;
		}
		default:
			dprintf("invalid spaceid %" B_PRId8 "\n", reg->reg_spaceid);
			break;
	}
	cState->pData = ci;
	cState->EnterIdle = acpi_cstate_idle;

	return B_OK;
}