summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/cpu/x86log.cpp
blob: 4ed80f061314d8331d71ea1cc039914286b42d1f (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                                





                                                                            

                                                                            

                  
                
                   



                                                                            


                                                                            
                                                    
                                                                                    















                                                                            
                                                   

                                   
                                       










                                                   
                                                      

                                  
                                 


                                  
                         



                                                   



                                                   
                                                                                             
 
                           




























                                                                                                    

                                                                               


                                      
                             






















                                                                                  



                                                                                                                                  












                                                                            
                                                                                                                   























                                                                                                            








                                                                            
                                                   




                                                   
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    x86log.c

    x86/x64 code logging helpers.

***************************************************************************/

#include <cstdint>
#include <cassert>
#include "emu.h"
#include "x86log.h"



/***************************************************************************
    FUNCTION PROTOTYPES
***************************************************************************/

static void reset_log(x86log_context *log) noexcept;
extern int i386_dasm_one_ex(char *buffer, UINT64 eip, const UINT8 *oprom, int mode);



/***************************************************************************
    EXTERNAL INTERFACES
***************************************************************************/

/*-------------------------------------------------
    x86log_create_context - create a new context
-------------------------------------------------*/

x86log_context *x86log_create_context(const char *filename)
{
	x86log_context *log;

	/* allocate the log */
	log = global_alloc_clear<x86log_context>();

	/* allocate the filename */
	log->filename.assign(filename);

	/* reset things */
	reset_log(log);
	return log;
}


/*-------------------------------------------------
    x86log_free_context - release a context
-------------------------------------------------*/

void x86log_free_context(x86log_context *log) noexcept
{
	/* close any open files */
	if (log->file != nullptr)
		fclose(log->file);

	/* free the structure */
	global_free(log);
}


/*-------------------------------------------------
    x86log_mark_as_data - mark a given range as
    data for logging purposes
-------------------------------------------------*/

void x86log_mark_as_data(x86log_context *log, x86code *base, x86code *end, int size) noexcept
{
	data_range_t *data;

	assert(log->data_range_count < MAX_DATA_RANGES);
	assert(end >= base);
	assert(size == 1 || size == 2 || size == 4 || size == 8);

	/* we assume data ranges are registered in order; enforce this */
	assert(log->data_range_count == 0 || base > log->data_range[log->data_range_count - 1].end);

	/* if we exceed the maxima, skip it */
	if (log->data_range_count >= MAX_DATA_RANGES)
		return;

	/* fill in the new range */
	data = &log->data_range[log->data_range_count++];
	data->base = base;
	data->end = end;
	data->size = size;
}


/*-------------------------------------------------
    x86log_disasm_code_range - disassemble a range
    of code and reset accumulated information
-------------------------------------------------*/

void x86log_disasm_code_range(x86log_context *log, const char *label, x86code *start, x86code *stop)
{
	const log_comment *lastcomment = &log->comment_list[log->comment_count];
	const log_comment *curcomment = &log->comment_list[0];
	const data_range_t *lastdata = &log->data_range[log->data_range_count];
	const data_range_t *curdata = &log->data_range[0];
	x86code *cur = start;

	/* print the optional label */
	if (label != nullptr)
		x86log_printf(log, "\n%s\n", label);

	/* loop from the start until the cache top */
	while (cur < stop)
	{
		char buffer[100];
		int bytes;

		/* skip past any past data ranges */
		while (curdata < lastdata && cur > curdata->end)
			curdata++;

		/* skip past any past comments */
		while (curcomment < lastcomment && cur > curcomment->base)
			curcomment++;

		/* if we're in a data range, output the next chunk and continue */
		if (cur >= curdata->base && cur <= curdata->end)
		{
			bytes = curdata->size;
			switch (curdata->size)
			{
				default:
				case 1:     sprintf(buffer, "db      %02X", *cur);              break;
				case 2:     sprintf(buffer, "dw      %04X", *(UINT16 *)cur);    break;
				case 4:     sprintf(buffer, "dd      %08X", *(UINT32 *)cur);    break;
				case 8:     sprintf(buffer, "dq      %08X%08X", ((UINT32 *)cur)[1], ((UINT32 *)cur)[0]);    break;
			}
		}

		/* if we're not in the data range, skip filler opcodes */
		else if (*cur == 0xcc)
		{
			cur++;
			continue;
		}

		/* otherwise, do a disassembly of the current instruction */
		else
		{
			bytes = i386_dasm_one_ex(buffer, (FPTR)cur, cur, sizeof(void *) * 8) & DASMFLAG_LENGTHMASK;
		}

		/* if we have a matching comment, output it */
		if (curcomment < lastcomment && cur == curcomment->base)
		{
			/* if we have additional matching comments at the same address, output them first */
			for ( ; curcomment + 1 < lastcomment && cur == curcomment[1].base; curcomment++)
				x86log_printf(log, "%p: %-50s; %s\n", cur, "", curcomment->string);
			x86log_printf(log, "%p: %-50s; %s\n", cur, buffer, curcomment->string);
		}

		/* if we don't, just print the disassembly and move on */
		else
			x86log_printf(log, "%p: %s\n", cur, buffer);

		/* advance past this instruction */
		cur += bytes;
	}

	/* reset our state */
	reset_log(log);
}



/***************************************************************************
    LOCAL FUNCTIONS
***************************************************************************/

/*-------------------------------------------------
    reset_log - reset the state of the log
-------------------------------------------------*/

static void reset_log(x86log_context *log) noexcept
{
	log->data_range_count = 0;
	log->comment_count = 0;
	log->comment_pool_next = log->comment_pool;
}