📄 mcf5xxx_hi.c
字号:
/*
* File: src/cpu/coldfire/mcf5xxx/mcf5xxx_hi.c
* Purpose: Higher level processing for MCF52xx processors.
*
* Notes:
*
*/
/********************************************************************/
#include "src/include/dbug.h"
#include "src/uif/cpu.h"
#include "src/uif/bkpt.h"
/********************************************************************/
/*
* This defines the data structure which will hold the values
* of the registers of the user task.
*/
REGISTERS context;
/********************************************************************/
/*
* This structure contains info about the registers. The name
* is given so that users can type it.
*/
typedef struct
{
const char * name;
const void * ptr;
const int size;
} reg_entry;
/*
* The method for specifying the pointer to the register in the
* 'context' data structure is to ensure that no matter which
* compiler is used, the offsets are the same. (ANSI C doesn't
* specify how the context of a structure/array are stored.)
*/
static const reg_entry registers[] =
{
{ "D0", &context.d0, 32 },
{ "D1", &context.d1, 32 },
{ "D2", &context.d2, 32 },
{ "D3", &context.d3, 32 },
{ "D4", &context.d4, 32 },
{ "D5", &context.d5, 32 },
{ "D6", &context.d6, 32 },
{ "D7", &context.d7, 32 },
{ "A0", &context.a0, 32 },
{ "A1", &context.a1, 32 },
{ "A2", &context.a2, 32 },
{ "A3", &context.a3, 32 },
{ "A4", &context.a4, 32 },
{ "A5", &context.a5, 32 },
{ "A6", &context.a6, 32 },
{ "A7", &context.a7, 32 },
{ "PC", &context.pc, 32 },
{ "SR", &context.sr, 16 },
{ "SP", &context.a7, 32 },
} ;
#define REGTAB_SIZE (int)(sizeof(registers) / sizeof(reg_entry))
/********************************************************************/
/*
* When cpu_handler() returns, a value of 0 means restore the context
* and perform an RTE to continue executing code. A non-zero return
* value drops back to the command prompt.
*/
#define EXEC_RTE 0
#define EXEC_DBUG 1
/********************************************************************/
static const char INVREG[] = "Error: Invalid Register: %s\n";
ADDRESS
cpu_step_over;
int
cpu_trace_count;
static ADDRESS
trace_thru;
#if (defined(CPU_MCF5272))
extern void ext_irq6_handler(void);
#endif
/********************************************************************/
static int
find_register (char *reg)
{
int index;
for (index = 0; index < REGTAB_SIZE; index++)
{
if (strcasecmp(registers[index].name,reg) == 0)
return index;
}
return -1;
}
/********************************************************************/
static void
dump_sr (uint16 sr)
{
char sr_buffer[17];
register int i;
int32 mask = MCF5XXX_SR_T;
int32 result;
for (i = 0; i < 16; i++)
{
result = mask & sr;
mask = mask >> 1;
switch (i) /* going from left to right, don't be fooled */
{
case 0:
if (result)
sr_buffer[i] = 'T';
else
sr_buffer[i] = 't';
break;
case 1:
case 4:
case 8:
case 9:
case 10:
sr_buffer[i] = '.';
break;
case 2:
if (result)
sr_buffer[i] = 'S';
else
sr_buffer[i] = 's';
break;
case 3:
if (result)
sr_buffer[i] = 'M';
else
sr_buffer[i] = 'm';
break;
case 5:
case 6:
case 7:
if (result)
sr_buffer[i] = '1';
else
sr_buffer[i] = '0';
break;
case 11:
if (result)
sr_buffer[i] = 'X';
else
sr_buffer[i] = 'x';
break;
case 12:
if (result)
sr_buffer[i] = 'N';
else
sr_buffer[i] = 'n';
break;
case 13:
if (result)
sr_buffer[i] = 'Z';
else
sr_buffer[i] = 'z';
break;
case 14:
if (result)
sr_buffer[i] = 'V';
else
sr_buffer[i] = 'v';
break;
case 15:
if (result)
sr_buffer[i] = 'C';
else
sr_buffer[i] = 'c';
break;
default:
break;
}
}
sr_buffer[i] = 0;
printf("%s",sr_buffer);
}
/********************************************************************/
static void
dump_fs (void *framep)
{
int fault = MCF5XXX_RD_SF_FS(framep);
printf(" FS=%X, ",fault);
switch (fault)
{
case 0x04:
printf("Physical bus error on instruction fetch");
break;
case 0x08:
printf("Physical bus error on operand write");
break;
case 0x09:
printf("Attempted write to write-protected space");
break;
case 0x0C:
printf("Physical bus error on operand read");
break;
default:
printf("Reserved");
break;
}
printf("\n");
}
/********************************************************************/
void
cpu_init (void)
{
trace_thru = NULL;
cpu_step_over = NULL;
cpu_trace_count = 0;
context.sr = MCF5XXX_SR_S;
}
/********************************************************************/
void
cpu_reg_modify (char *reg, uint32 value)
{
int index;
if ((index = find_register(reg)) != -1)
{
switch (registers[index].size)
{
case SIZE_16:
*(uint16 *)registers[index].ptr = (uint16)value;
break;
case SIZE_32:
default:
*(uint32 *)registers[index].ptr = (uint32)value;
break;
}
}
else
{
printf(INVREG,reg);
}
}
/********************************************************************/
void
cpu_reg_display (char *reg)
{
int index;
if (reg == NULL)
{
printf("PC: %08X ", context.pc);
printf("SR: %04X [", context.sr);
dump_sr(context.sr);
printf("]\n");
printf("An: %08X %08X %08X %08X %08X %08X %08X %08X\n",
context.a0,
context.a1,
context.a2,
context.a3,
context.a4,
context.a5,
context.a6,
context.a7 );
printf("Dn: %08X %08X %08X %08X %08X %08X %08X %08X\n",
context.d0,
context.d1,
context.d2,
context.d3,
context.d4,
context.d5,
context.d6,
context.d7 );
}
else
{
if ((index = find_register(reg)) != -1)
{
switch (registers[index].size)
{
case SIZE_16:
printf("%s: %04X\n",
registers[index].name,
*(uint16 *)(registers[index].ptr));
break;
case SIZE_32:
default:
printf("%s: %08X\n",
registers[index].name,
*(uint32 *)(registers[index].ptr));
}
}
else
{
printf(INVREG,reg);
}
}
}
/********************************************************************/
void
cpu_pc_modify (ADDRESS address)
{
context.pc = address;
}
/********************************************************************/
ADDRESS
cpu_pc_get (void)
{
return context.pc;
}
/********************************************************************/
int
cpu_parse_size (char *arg)
{
int i, size = SIZE_16;
for (i = 0; arg[i] != '\0'; i++)
{
if (arg[i] == '.')
{
switch (arg[i+1])
{
case 'b':
case 'B':
size = SIZE_8;
break;
case 'w':
case 'W':
size = SIZE_16;
break;
case 'l':
case 'L':
size = SIZE_32;
break;
default:
size = SIZE_16;
break;
}
break;
}
}
return size;
}
/********************************************************************/
int
cpu_valid_insn_addr (ADDRESS address)
{
/* ColdFire requires instructions be on 16-bit boundary */
return !(address & 0x00000001);
}
/********************************************************************/
void
cpu_switch_context (int trace)
{
/*
* If 'trace' is TRUE, then we are performing a single
* instruction trace, thus, do not insert breakponts.
* Otherwise, install breakpoints and run normally.
*/
if (trace)
{
context.sr |= MCF5XXX_SR_T;
}
else
{
if (breakpoint_install(context.pc))
{
/*
* The PC is at a breakpoint already. Trace thru
* this breakpoint rather than actually breaking.
*/
trace_thru = context.pc;
context.sr |= MCF5XXX_SR_T;
}
}
asm_switch_context(&context);
}
/********************************************************************/
void
cpu_write_data (ADDRESS address, int size, uint32 data)
{
switch (size)
{
case SIZE_8:
*((uint8 *)address) = (uint8)data;
break;
case SIZE_16:
*((uint16 *)address) = (uint16)data;
break;
case SIZE_32:
*((uint32 *)address) = (uint32)data;
break;
default:
break;
}
}
/********************************************************************/
uint32
cpu_read_data (ADDRESS address, int size)
{
switch (size)
{
case SIZE_8:
return *((uint8 *)address);
break;
case SIZE_16:
return *((uint16 *)address);
break;
case SIZE_32:
return *((uint32 *)address);
break;
default:
return 0;
break;
}
}
/********************************************************************/
ADDRESS
cpu_align_address (ADDRESS address, int size)
{
switch (size)
{
case SIZE_16:
return (address & ~0x00000001);
break;
case SIZE_32:
return (address & ~0x00000003);
break;
case SIZE_8:
default:
return (address);
break;
}
}
/********************************************************************/
ADDRESS
cpu_stack_frame (ADDRESS fp, ADDRESS *retpc)
{
/*
* ColdFire/M68K JSR w/LINK and UNLK w/RTS
*/
if (retpc == NULL)
{
return context.a6;
}
else
{
*retpc = *(ADDRESS *)(fp + 4);
return *(ADDRESS *)fp;
}
}
/********************************************************************/
int
cpu_handler (void *framep)
{
/*
* This is the exception handler for all defined exceptions. Most
* exceptions do nothing, but some of the more important ones are
* handled to some extent.
*/
int ispdelta;
int cpu_handler_flag;
int user_brkpnt, user_triggered;
/*
* Default action for most exceptions is to break to monitor.
*/
cpu_handler_flag = EXEC_DBUG;
/*
* Update context.sp to point to prior to stack frame.
*/
switch (MCF5XXX_RD_SF_FORMAT(framep))
{
case 4:
ispdelta = 8;
break;
case 5:
ispdelta = 9;
break;
case 6:
ispdelta = 10;
break;
case 7:
ispdelta = 11;
break;
default:
printf("\nIllegal stack type!\n");
ispdelta = 0;
break;
}
context.a7 += ispdelta;
user_brkpnt = breakpoint_deinstall(context.pc, &user_triggered);
switch (MCF5XXX_RD_SF_VECTOR(framep))
{
case 2:
printf("Access Error: ");
dump_fs(framep);
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
case 3:
printf("Address Error: ");
dump_fs(framep);
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
case 4:
if (!user_brkpnt)
{
printf("Illegal instruction at %#08X\n",context.pc);
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
}
if (cpu_step_over == context.pc)
{
/* clean up is at end of handler */
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
}
if (user_triggered)
{
printf("Breakpoint encountered at %#08X\n",context.pc);
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
}
/* else reinstall breakpoints and continue */
/* execution of the task...we will return */
/* to task from here, not write out regs and RTE */
if (breakpoint_install(context.pc))
{
/* about to execute at a breakpoint */
/* trace thru this breakpoint rather breaking */
trace_thru = context.pc;
/* turn tracing on */
MCF5XXX_SF_SR(framep) |= MCF5XXX_SR_T;
/* readjust stack pointer for RTE */
context.a7 -= ispdelta;
cpu_handler_flag = EXEC_RTE;
}
break;
case 8:
printf("Privilege violation\n");
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
case 9:
if (trace_thru)
{
/* place breakpoint at trace_thru */
cpu_write_data(trace_thru, SIZE_16, ILLEGAL);
/* turn off tracing */
context.sr &= ~MCF5XXX_SR_T;
/* nullify trace_thru and continue execution */
trace_thru = 0;
cpu_handler_flag = EXEC_RTE;
/* adjust user stack back so RTE frame correct */
context.a7 -= ispdelta;
/* since not recreating a new stack frame, must */
/* turn off trace bit in SR already on stack. */
MCF5XXX_SF_SR(framep) &= ~MCF5XXX_SR_T;
break;
}
/* each time through, decrement cpu_trace_count */
if (--cpu_trace_count > 0)
{
context.a7 -= ispdelta;
cpu_handler_flag = EXEC_RTE;
}
else
{
/* since not recreating a new stack frame, must */
/* turn off trace bit in SR already on stack. */
MCF5XXX_SF_SR(framep) &= ~MCF5XXX_SR_T;
/* turn off tracing */
context.sr &= ~MCF5XXX_SR_T;
cpu_handler_flag = EXEC_DBUG;
cpu_trace_count = 0;
}
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
case 10:
printf("Unimplemented A-Line Instruction\n");
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
case 11:
printf("Unimplemented F-Line Instruction\n");
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
case 12:
printf("Debug Interrupt\n");
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
case 14:
printf("Format Error\n");
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
case 15:
printf("Unitialized Interrupt\n");
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
case 24:
printf("Spurious Interrupt\n");
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
case 31:
printf("Autovector interrupt level %d\n",
MCF5XXX_RD_SF_VECTOR(framep) - 24);
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
case 38:
case 39:
case 40:
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
printf("TRAP #%d\n", MCF5XXX_RD_SF_VECTOR(framep) - 32);
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
#if (defined(CPU_MCF5272))
case 91:
printf("External Interrupt 6\n");
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
ext_irq6_handler();
break;
#endif
case 5:
case 6:
case 7:
case 13:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 48:
case 49:
case 50:
case 51:
case 52:
case 53:
case 54:
case 55:
case 56:
case 57:
case 58:
case 59:
case 60:
case 61:
case 62:
case 63:
printf("Reserved: #%d\n",
MCF5XXX_RD_SF_VECTOR(framep));
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
default:
printf("User Defined Vector #%d\n",
MCF5XXX_RD_SF_VECTOR(framep));
cpu_reg_display(NULL);
cpu_disasm(context.pc,TRUE);
break;
}
if ((cpu_handler_flag == EXEC_DBUG) && cpu_step_over)
{
breakpoint_remove(cpu_step_over);
cpu_step_over = 0;
}
return cpu_handler_flag;
}
/********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -