diff --git a/src/leon3_dsu.c b/src/leon3_dsu.c index e449064bd70d0cddcd88cf2b6247fbccbf44909c..531dc6b22945fc683505e6bd0dd3c0c295403c4e 100644 --- a/src/leon3_dsu.c +++ b/src/leon3_dsu.c @@ -96,6 +96,9 @@ static uint32_t dsu_get_local_reg_addr(uint32_t cpu, uint32_t n, uint32_t cwp) } + + + /** * @brief calculate address of input register %in for a window * @see GR712-UM v2.3 pp. 81 @@ -415,6 +418,133 @@ uint32_t dsu_get_reg_trap(uint32_t cpu) } + +/** + * @brief get input register of current window pointer + * + * @param cpu the cpu number + * + * @param buffer point to array where values will be written + */ +void dsu_get_input_reg(uint32_t cpu, uint32_t *buffer) +{ + uint32_t psr_reg = dsu_get_reg_psr(cpu); + uint32_t cwp = psr_reg & 0x1F; + + ioread32(DSU_REG_IN(cpu, cwp), buffer, 8); +} + + +/** + * @brief get local register of current window pointer + * + * @param cpu the cpu number + * + * @param buffer pointer to array where values will be written + */ +void dsu_get_local_reg(uint32_t cpu, uint32_t *buffer) +{ + uint32_t psr_reg = dsu_get_reg_psr(cpu); + uint32_t cwp = psr_reg & 0x1F; + + ioread32(DSU_REG_LOCAL(cpu, cwp), buffer, 8); +} + +/** + * @brief get output register of current window pointer + * + * @param cpu the cpu number + * + * @param buffer point to array where values will be written + */ +void dsu_get_output_reg(uint32_t cpu, uint32_t *buffer) +{ + uint32_t psr_reg = dsu_get_reg_psr(cpu); + uint32_t cwp = psr_reg & 0x1F; + + ioread32(DSU_REG_OUT(cpu, cwp), buffer, 8); +} + +/** + * @brief get gloabl register + * + * @param cpu the cpu number + * + * @param buffer point to array where values will be written + */ +void dsu_get_global_reg(uint32_t cpu, uint32_t *buffer) +{ + ioread32(DSU_REG_GLOBAL(cpu), buffer, 8); +} + +void dsu_get_local_reg_window(uint32_t cpu, uint32_t window, uint32_t *buffer) +{ + ioread32(DSU_REG_LOCAL(cpu, window), buffer, 8); +} + + +void dsu_get_input_reg_window(uint32_t cpu, uint32_t window, uint32_t *buffer) +{ + ioread32(DSU_REG_IN(cpu, window), buffer, 8); +} + + +void dsu_get_output_reg_window(uint32_t cpu, uint32_t window, uint32_t *buffer) +{ + ioread32(DSU_REG_OUT(cpu, window), buffer, 8); +} + + +uint32_t dsu_get_local_reg_single(uint32_t cpu, uint32_t cwp, uint32_t reg_num) +{ + return ioread32(dsu_get_local_reg_addr(cpu, reg_num, cwp)); +} + +uint32_t dsu_get_input_reg_single(uint32_t cpu, uint32_t cwp, uint32_t reg_num) +{ + return ioread32(dsu_get_input_reg_addr(cpu, reg_num, cwp)); +} + +uint32_t dsu_get_output_reg_single(uint32_t cpu, uint32_t cwp, uint32_t reg_num) +{ + return ioread32(dsu_get_output_reg_addr(cpu, reg_num, cwp)); +} + +uint32_t dsu_get_global_reg_single(uint32_t cpu, uint32_t reg_num) +{ + return ioread32(dsu_get_global_reg_addr(cpu, reg_num)); +} + + +union float_value dsu_get_float_reg(uint32_t cpu, uint32_t reg_num) +{ + union float_value val = {0}; + + if (reg_num > 31) + return val; + + val.u = ioread32(DSU_BASE(cpu) + DSU_FPU_REG + reg_num * 4); + return val; +} + + +union double_value dsu_get_double_reg(uint32_t cpu, uint32_t reg_num) +{ + uint32_t address = DSU_BASE(cpu) + DSU_FPU_REG + 32 * 4 + reg_num * 8; + union double_value val = {0}; + + if (reg_num > 12) + return val; + + val.u = (uint64_t)ioread32(address); + val.u = val.u << 32; + val.u += (uint64_t)ioread32(address + 4); + + return val; +} + + + /** * @brief check if cpu is in debug mode * @@ -921,6 +1051,20 @@ void dsu_set_reg_fp(uint32_t cpu, uint32_t cwp, uint32_t val) } +/** + * @brief get frame pointer register (%i6) in a window of a cpu + * + * @param cpu the cpu number + * @param cwp the window number + */ +uint32_t dsu_get_reg_fp(uint32_t cpu, uint32_t cwp) +{ + uint32_t reg = dsu_get_input_reg_addr(cpu, 6, cwp); + + return ioread32(reg); +} + + /** * @brief get the last line_count lines from the instruction trace buffer @@ -980,5 +1124,59 @@ void dsu_get_instr_trace_buffer(uint32_t cpu, struct instr_trace_buffer_line *bu } } - free(data); + free(data); +} + + +void dsu_set_local_reg(uint32_t cpu, uint32_t cwp, uint32_t reg_num, uint32_t value) +{ + uint32_t address = dsu_get_local_reg_addr(cpu, reg_num, cwp); + + iowrite32(address, value); +} + + +void dsu_set_input_reg(uint32_t cpu, uint32_t cwp, uint32_t reg_num, uint32_t value) +{ + uint32_t address = dsu_get_input_reg_addr(cpu, reg_num, cwp); + + iowrite32(address, value); +} + + +void dsu_set_output_reg(uint32_t cpu, uint32_t cwp, uint32_t reg_num, uint32_t value) +{ + uint32_t address = dsu_get_output_reg_addr(cpu, reg_num, cwp); + + iowrite32(address, value); +} + + +void dsu_set_global_reg(uint32_t cpu, uint32_t reg_num, uint32_t value) +{ + uint32_t address = dsu_get_global_reg_addr(cpu, reg_num); + + iowrite32(address, value); +} + + +void dsu_set_float_reg(uint32_t cpu, uint32_t reg_num, union float_value value) +{ + uint32_t address = DSU_BASE(cpu) + DSU_FPU_REG + reg_num * 4; + if (reg_num > 31) + return; + + iowrite32(address, value.u); +} + + +void dsu_set_double_reg(uint32_t cpu, uint32_t reg_num, union double_value value) +{ + uint32_t address = DSU_BASE(cpu) + DSU_FPU_REG + 32 * 4 + reg_num * 8; + + if (reg_num > 12) + return; + + iowrite32(address, (uint32_t)(value.u >> 32)); + iowrite32(address + 4, (uint32_t)(value.u & 0xFFFFFFFF)); } diff --git a/src/leon3_dsu.h b/src/leon3_dsu.h index 680e8eba2d777ac21ffb4b5b4159a6e9adab94db..cded64baa8bdb70729c001a804c0fbd76094cfaa 100644 --- a/src/leon3_dsu.h +++ b/src/leon3_dsu.h @@ -91,6 +91,8 @@ #define DSU_REG_TRAP 0x400020 + + // TODO: this needs to be refactored #define DSU_CTRL ADDRESSES[get_connected_cpu_type()][DSU] #define DSU_OFFSET_CPU(x) ((x & 0x07) << 24) @@ -98,6 +100,12 @@ //#define DSU_BASE(x) (ADDRESSES[get_connected_cpu_type()][DSU] + DSU_OFFSET_CPU(x)) +#define DSU_REG_OUT(cpu, cwp) DSU_BASE(cpu) + DSU_IU_REG + ((cwp * 64 + 32) % (NWINDOWS * 64)) +#define DSU_REG_LOCAL(cpu, cwp) DSU_BASE(cpu) + DSU_IU_REG + ((cwp * 64 + 64) % (NWINDOWS * 64)) +#define DSU_REG_IN(cpu, cwp) DSU_BASE(cpu) + DSU_IU_REG + ((cwp * 64 + 96) % (NWINDOWS * 64)) +#define DSU_REG_GLOBAL(cpu) DSU_BASE(cpu) + DSU_IU_REG + (NWINDOWS * 64) + + /** * @see GR712-UM v2.3 p. 82 @@ -232,6 +240,18 @@ struct ahb_trace_buffer_line { }__attribute__((packed)); + +union float_value { + uint32_t u; + float f; +}; + +union double_value { + uint64_t u; + double d; +}; + + /** * maps the AHB trace buffer, must be pointed to DSU_AHB_TRCE_BUF_START */ @@ -261,7 +281,27 @@ uint32_t dsu_get_global_reg(uint32_t cpu, uint32_t n); uint32_t dsu_get_dsu_ctrl(uint32_t cpu); uint32_t dsu_get_reg_psr(uint32_t cpu); uint32_t dsu_get_reg_tbr(uint32_t cpu); +uint32_t dsu_get_reg_y(uint32_t cpu); uint32_t dsu_get_reg_trap(uint32_t cpu); + +void dsu_get_local_reg(uint32_t cpu, uint32_t *buffer); +void dsu_get_input_reg(uint32_t cpu, uint32_t *buffer); +void dsu_get_output_reg(uint32_t cpu, uint32_t *buffer); +void dsu_get_global_reg(uint32_t cpu, uint32_t *buffer); + +void dsu_get_local_reg_window(uint32_t cpu, uint32_t cwp, uint32_t *buffer); +void dsu_get_input_reg_window(uint32_t cpu, uint32_t cwp, uint32_t *buffer); +void dsu_get_output_reg_window(uint32_t cpu, uint32_t cwp, uint32_t *buffer); + +uint32_t dsu_get_local_reg_single(uint32_t cpu, uint32_t cwp, uint32_t reg_num); +uint32_t dsu_get_input_reg_single(uint32_t cpu, uint32_t cwp, uint32_t reg_num); +uint32_t dsu_get_output_reg_single(uint32_t cpu, uint32_t cwp, uint32_t reg_num); +uint32_t dsu_get_global_reg_single(uint32_t cpue, uint32_t cwp, uint32_t reg_num); + +union float_value dsu_get_float_reg(uint32_t cpu, uint32_t reg_num); +union double_value dsu_get_double_reg(uint32_t cpu, uint32_t reg_num); + + void dsu_set_reg_psr(uint32_t cpu, uint32_t val); /* line_start is relative with 0 being the last executed line */ @@ -270,6 +310,7 @@ void dsu_get_instr_trace_buffer(uint32_t cpu, struct instr_trace_buffer_line *bu uint32_t dsu_get_reg_wim(uint32_t cpu); uint32_t dsu_get_reg_pc(uint32_t cpu); uint32_t dsu_get_reg_sp(uint32_t cpu, uint32_t cwp); +uint32_t dsu_get_reg_fp(uint32_t cpu, uint32_t cwp); uint32_t dsu_get_reg_fsr(uint32_t cpu); @@ -294,4 +335,14 @@ void dsu_set_reg_fsr(uint32_t cpu, uint32_t val); void dsu_set_reg_sp(uint32_t cpu, uint32_t cwp, uint32_t val); void dsu_set_reg_fp(uint32_t cpu, uint32_t cwp, uint32_t val); +void dsu_set_local_reg(uint32_t cpu, uint32_t cwp, uint32_t reg_num, uint32_t value); +void dsu_set_input_reg(uint32_t cpu, uint32_t cwp, uint32_t reg_num, uint32_t value); +void dsu_set_output_reg(uint32_t cpu, uint32_t cwp, uint32_t reg_num, uint32_t value); +void dsu_set_global_reg(uint32_t cpu, uint32_t reg_num, uint32_t value); + +void dsu_set_float_reg(uint32_t cpu, uint32_t reg_num, union float_value value); +void dsu_set_double_reg(uint32_t cpu, uint32_t reg_num, union double_value value); + + + #endif /* LEON3_DSU_H */ diff --git a/src/uviemon_cli.cpp b/src/uviemon_cli.cpp index 8594fa5c3bd8181b822f0bfeff89b933c4e6886c..b43c860a629a3bd1a64ffb4dcb51ca13621533ed 100644 --- a/src/uviemon_cli.cpp +++ b/src/uviemon_cli.cpp @@ -12,6 +12,7 @@ #include "uviemon_cli.hpp" #include "address_map.h" +#include "uviemon_reg.h" #include <iostream> // cout & cerr #include <iomanip> // Used for setfill and setw (cout formatting) @@ -20,6 +21,28 @@ #include <stdlib.h> +#ifndef PACKAGE + #define PACKAGE + #ifndef PACKAGE_VERSION + #define PACKAGE_VERSION + #include <bfd.h> + #undef PACKAGE_VERSION + #else + #include <bfd.h> + #endif + #undef PACKAGE +#else + #ifndef PACKAGE_VERSION + #define PACKAGE_VERSION + #include <bfd.h> + #undef PACKAGE_VERSION + #else + #include <bfd.h> + #endif +#endif + +#include <dis-asm.h> + #include "leon3_dsu.h" @@ -27,7 +50,7 @@ using namespace std; //static int command_count; -#define COMMAND_COUNT 14 +#define COMMAND_COUNT 16 static command commands[COMMAND_COUNT] = { { "help", &help }, @@ -45,6 +68,9 @@ static command commands[COMMAND_COUNT] = { { "bdump", &bdump }, { "inst", &inst }, + { "reg", ® }, + + { "wash", &washc }, { "load", &load }, { "verify", &verify }, @@ -56,8 +82,14 @@ static command commands[COMMAND_COUNT] = { static DWORD parse_parameter(char *param); static void parse_opcode(char *buffer, uint32_t opcode, uint32_t address); +static void print_register_error_msg(const char * const reg); +static void print_value_error_msg(const char * const value); +//static int parse_register_number(const char * const reg, uint32_t * const reg_num, uint32_t highest_register); +static const char * const get_tt_error_desc(uint32_t error_code); + +#define TT_ERROR_COUNT 32 -std::unordered_map<int, std::string> tt_errors = { +struct tt_error tt_errors[] = { {0x0, "[reset]: Power-on reset"}, {0x2b, "[write_error]: write buffer error"}, {0x01, "[instruction_access_error]: Error during instruction fetch"}, @@ -90,7 +122,7 @@ std::unordered_map<int, std::string> tt_errors = { {0x1E, "[interrupt_level_14]: Asynchronous interrupt 14"}, {0x1F, "[interrupt_level_15]: Asynchronous interrupt 15"}, {0x80, "[trap_instruction]: OK"} - // Anything larger than 0x80 will be some other Software trap instruction (TA) + /* Anything larger than 0x80 will be some other Software trap instruction (TA) */ }; @@ -259,7 +291,9 @@ void help(const char *command, int param_count, char params[MAX_PARAMETERS][MAX_ printf(" bdump:\t Read <length#2> BYTEs of data from memory starting at an <address#1>, saving the data to a <filePath#1>\n\n"); - printf(" isnt:\t Prints the last <instruction_cnt#1> instruction to stdout\n\n"); + printf(" inst:\t Prints the last <instruction_cnt#1> instruction to stdout\n\n"); + + printf(" reg:\t Prints or sets registers\n\n"); printf(" load: \t Write a file with <filePath#1> to the device memory\n"); printf(" verify: \t Verify a file written to the device memory with <filePath#1>\n"); @@ -284,26 +318,33 @@ void run(const char *command, int param_count, char params[MAX_PARAMETERS][MAX_P if (tt < 0x80) // Hardware traps { - cerr << " => Error: Hardware trap!" << endl; - cerr << endl; - cerr << "tt 0x" << hex << (unsigned int)tt << ", " << tt_errors[tt] << endl; + printf(" => Error: Hardware trap!\n\n"); + printf("tt 0x%02x, %s\n", (uint8_t)tt, get_tt_error_desc(tt)); } else if (tt == 0x80) // Successfull trap { - cout << " => OK!" << endl; + printf(" => OK!\n"); } else if (tt > 0x80 && tt <= 0xFF) // Software trap { - cerr << " => Error: Software trap!" << endl; - cerr << endl; - cerr << "tt 0x" << hex << (unsigned int)tt << ", [trap_instruction]: Software trap instruction (TA)" << endl; + printf(" => Error: Software trap!\n\n"); + printf("tt 0x%02x, [trap_instruction]: Software trap instruction (TA)\n", (uint8_t)tt); } else // Something else that's not documented { - cerr << " => Error!" << endl; - cerr << endl; - cerr << "tt 0x" << hex << (unsigned int)tt << ", [unknown]: unknown trap!" << endl; + printf(" => Error!\n\n"); + printf("tt 0x%02x, [unknown]: unknown trap!", (uint8_t)tt); + } +} + +static const char * const get_tt_error_desc(uint32_t error_code) +{ + for (int i = 0; i < TT_ERROR_COUNT; i++) { + if (tt_errors[i].error_code == error_code) + return tt_errors[i].error_desc; } + + return "Error code not found"; } void reset(const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]) @@ -355,7 +396,7 @@ void verify(const char *command, int param_count, char params[MAX_PARAMETERS][MA verify(params[0]); } -void wash(const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]) +void washc(const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]) { WORD size = 16; // was 0x40000000 @@ -410,11 +451,11 @@ void memx(const char *command, int param_count, char params[MAX_PARAMETERS][MAX_ } if (strcmp(command, "memh") == 0) { - param_count == 1 ? memh(param_1) : memh(param_1, param_2); + param_count == 1 ? memh(param_1, 32) : memh(param_1, param_2); } else if(strcmp(command, "memb") == 0) { - param_count == 1 ? memb(param_1) : memb(param_1, param_2); + param_count == 1 ? memb(param_1, 64) : memb(param_1, param_2); } else if (strcmp(command, "mem") == 0) { - param_count == 1 ? mem(param_1) : mem(param_1, param_2); + param_count == 1 ? mem(param_1, 16) : mem(param_1, param_2); } } @@ -427,13 +468,14 @@ void wmemx(const char *command, int param_count, char params[MAX_PARAMETERS][MAX return; } - if ( (param_1 = strtol(params[0], NULL, 10)) == 0) { - printf("Parameter 1 must be a positive integer"); + if ( (param_1 = parse_parameter(params[0])) == 0) { + printf("Parameter 1 must be a positive integer\n"); return; } - if ( (param_2 = strtol(params[1], NULL, 10)) == 0) { - printf("Parameter 2 must be a positive integer"); + param_2 = parse_parameter(params[1]); + if (errno != 0) { + printf("Parameter 2 a 32 bit int\n"); return; } @@ -450,6 +492,7 @@ void wmemx(const char *command, int param_count, char params[MAX_PARAMETERS][MAX void inst(const char* command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]) { uint32_t instr_count = 11; + uint32_t cpu = 0; if (param_count > 1) { printf("Inst only needs 1 parameter: the number of lines"); @@ -467,7 +510,7 @@ void inst(const char* command, int param_count, char params[MAX_PARAMETERS][MAX_ struct instr_trace_buffer_line *buffer = (instr_trace_buffer_line*) malloc(sizeof(instr_trace_buffer_line) * instr_count * 2); /* TODO: manage active cpu */ - dsu_get_instr_trace_buffer(0, buffer, instr_count * 2, 0); + dsu_get_instr_trace_buffer(cpu, buffer, instr_count * 2, 0); uint32_t i_cntr = 0; @@ -487,7 +530,7 @@ void inst(const char* command, int param_count, char params[MAX_PARAMETERS][MAX_ if (i_cntr < instr_count) { page++; - dsu_get_instr_trace_buffer(0, buffer, instr_count * 2, page * instr_count * 2); + dsu_get_instr_trace_buffer(cpu, buffer, instr_count * 2, page * instr_count * 2); } } @@ -508,10 +551,10 @@ void inst(const char* command, int param_count, char params[MAX_PARAMETERS][MAX_ * second is program counter with last two bits set to zero */ parse_opcode(operation, buffer[j].field[3], buffer[j].field[2] & 0xFFFFFFFC); - printf(" %9u %08x %-30s [", + printf(" %9u %08x ", buffer[j].field[0] & 0x3FFFFFFF, - buffer[j].field[2] & 0xFFFFFFFC, - operation); + buffer[j].field[2] & 0xFFFFFFFC); + printf(" ["); /* Check for instruction trap bit 2 is set */ @@ -537,9 +580,166 @@ void inst(const char* command, int param_count, char params[MAX_PARAMETERS][MAX_ free(buffer); } +void reg (const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]) +{ + uint32_t cpu = 0; + uint32_t input, reg_value; + int base; + char *input_str; + + union float_value reg_value_float, float_input; + union double_value reg_value_double, double_input; + + struct register_desc desc; + struct register_func *func_handler; + + if (param_count == 0) { + uint32_t cwp = dsu_get_reg_psr(cpu) & 0x1F; + register_print_summary(cpu, cwp); + + } else { + desc = parse_register(params[0], cpu); + + /* Register could not be parsed */ + if (strcmp(desc.name, "inv") == 0) { + print_register_error_msg(params[0]); + return; + } + + /* Print register summary for the requested window */ + if (strcmp(desc.name, "w") == 0) { + register_print_summary(cpu, desc.window); + return; + } + + /* Get function pointer for getting and setting requsted register */ + func_handler = get_register_functions(desc); + + if (strcmp(func_handler->name, "inv") == 0) { + print_register_error_msg(params[0]); + return; + } + + /* Parse value from second parameter if available */ + if (param_count == 2) { + input_str = params[1]; + base = 10; + errno = 0; + + switch(desc.type) { + case standard_reg: + if (input_str[0] == '0' && input_str[1] == 'x') { + base = 16; + input_str = input_str + 2; + } + + input = strtol(input_str, NULL, base); + + if (errno != 0) { + print_value_error_msg(params[1]); + return; + } + + ((register_func_standard*)func_handler)->set_value(desc, input); + break; + + case float_reg: + float_input.f = strtof(input_str, NULL); + + if (errno != 0) { + print_value_error_msg(params[1]); + return; + } + + ((register_func_float*)func_handler)->set_value(desc, float_input); + break; + + case double_reg: + double_input.d = strtod(input_str, NULL); + + if (errno != 0) { + print_value_error_msg(params[1]); + return; + } + + ((register_func_double*)func_handler)->set_value(desc, double_input); + break; + + default: + break; + } + } + + switch(desc.type) { + case standard_reg: + reg_value = ((register_func_standard*)func_handler)->get_value(desc); + printf(" %3s = %d (0x%08x)\n", params[0], reg_value, reg_value); + break; + + case float_reg: + reg_value_float = ((register_func_float*)func_handler)->get_value(desc); + printf(" %3s = %f (0x%08x)\n", params[0], reg_value_float.f, reg_value_float.u); + break; + + case double_reg: + reg_value_double = ((register_func_double*)func_handler)->get_value(desc); + printf(" %3s = %lf (0x%016lx)\n", params[0], reg_value_double.d, reg_value_double.u); + break; + + case none: + print_register_error_msg(params[0]); + break; + } + } + +} + +static void print_register_error_msg(const char * const reg) +{ + printf("No such register %s\n", reg); +} + +static void print_value_error_msg(const char * const value) +{ + printf("Could not parse value: %s\n", value); +} + static void parse_opcode(char *buffer, uint32_t opcode, uint32_t address) { + /* list supported arch */ + /*const char **arch_list = bfd_arch_list(); + const char **a; + + for (a = arch_list; *a; a++) { + printf("\t%s\n", *a); + } + + free(arch_list); + + + static bool disassembler_initialized = false; + static disassembler_ftype disassembler_p; + static disassemble_info info; + + if (!disassembler_initialized) { + disassembler_p = disassembler(bfd_arch_sparc, true, bfd_mach_sparc, NULL); + + init_disassemble_info(&info, stdout, (fprintf_ftype)fprintf, (fprintf_styled_ftype)fprintf); + info.read_memory_func = buffer_read_memory; + info.buffer_vma = address; + info.arch = bfd_arch_sparc; + info.mach = bfd_mach_sparc_v8plus; + disassemble_init_for_target(&info); + + disassembler_initialized = true; + } + + info.buffer = (bfd_byte *)&opcode; + info.buffer_length = 1; + + disassembler_p(0, &info);*/ + struct opcode op; op.opcode_raw = opcode; diff --git a/src/uviemon_cli.hpp b/src/uviemon_cli.hpp index 0e9931dbce65913dd006a5eacb99f7d156b1a18e..40ca86e9082929734f6b75d68a48a44a1beea5c5 100644 --- a/src/uviemon_cli.hpp +++ b/src/uviemon_cli.hpp @@ -30,12 +30,8 @@ typedef struct { void (*function)(const char *, int, char [MAX_PARAMETERS][MAX_PARAM_LENGTH]); } command; -typedef struct { - -} command_parameter; - -extern std::unordered_map<int, std::string> tt_errors; +//extern std::unordered_map<int, std::string> tt_errors; std::string _hexToString(DWORD *data, size_t size); std::string _hexToString(WORD *data, size_t size); @@ -101,6 +97,13 @@ struct opcode { }; }__attribute__((packed)); + +struct tt_error { + uint32_t error_code; + const char * const error_desc; +}; + + /* Command functions */ void help (const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]); void scan (const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]); @@ -111,20 +114,22 @@ void reset (const char *command, int param_count, char params[MAX_PARAMETERS][MA void load (const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]); void verify(const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]); void bdump (const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]); -void wash (const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]); +void washc (const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]); void inst (const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]); +void reg (const char *command, int param_count, char params[MAX_PARAMETERS][MAX_PARAM_LENGTH]); + void wmem(DWORD addr, DWORD data); void wmemh(DWORD addr, WORD data); void wmemb(DWORD addr, BYTE data); -void mem(DWORD startAddr, DWORD length = 16); -void memh(DWORD startAddr, DWORD length = 32); -void memb(DWORD startAddr, DWORD length = 64); +void mem(DWORD startAddr, DWORD length); +void memh(DWORD startAddr, DWORD length); +void memb(DWORD startAddr, DWORD length); void bdump(DWORD startAddr, DWORD length, std::string path); -void wash(WORD size = 16, DWORD addr = 0x40000000, DWORD c = 0); +void wash(WORD size, DWORD addr, DWORD c); void load(std::string path); void verify(std::string path); // Really slow because sequential reads are dead slow diff --git a/src/uviemon_reg.c b/src/uviemon_reg.c new file mode 100644 index 0000000000000000000000000000000000000000..fd625e5d5276ddfd41da54f61770f4bc842d38bb --- /dev/null +++ b/src/uviemon_reg.c @@ -0,0 +1,488 @@ +#include "uviemon_reg.h" + +#include <stdio.h> +#include <string.h> + +static int parse_register_number_single(const char reg_num, uint32_t *dest); +static int parse_register_number(const char * const reg, uint32_t * const reg_num, uint32_t highest_register); + +/* Special purpose registers */ + +static uint32_t get_reg_psr(struct register_desc desc); +static void set_reg_psr(struct register_desc desc, uint32_t value); + +static uint32_t get_reg_tbr(struct register_desc desc); +static void set_reg_tbr(struct register_desc desc, uint32_t value); + +static uint32_t get_reg_wim(struct register_desc desc); +static void set_reg_wim(struct register_desc desc, uint32_t value); + +static uint32_t get_reg_y(struct register_desc desc); +static void set_reg_y(struct register_desc desc, uint32_t value); + +static uint32_t get_reg_pc(struct register_desc desc); +static void set_reg_pc(struct register_desc desc, uint32_t value); + +static uint32_t get_reg_npc(struct register_desc desc); +static void set_reg_npc(struct register_desc desc, uint32_t value); + +static uint32_t get_reg_fsr(struct register_desc desc); +static void set_reg_fsr(struct register_desc desc, uint32_t value); + +static uint32_t get_reg_sp(struct register_desc desc); +static void set_reg_sp(struct register_desc desc, uint32_t value); + +static uint32_t get_reg_fp(struct register_desc desc); +static void set_reg_fp(struct register_desc desc, uint32_t value); + +/* Window registers */ + +static uint32_t get_reg_global(struct register_desc desc); +static void set_reg_global(struct register_desc desc, uint32_t value); + +static uint32_t get_reg_input(struct register_desc desc); +static void set_reg_input(struct register_desc desc, uint32_t value); + +static uint32_t get_reg_output(struct register_desc desc); +static void set_reg_output(struct register_desc desc, uint32_t value); + +static uint32_t get_reg_local(struct register_desc desc); +static void set_reg_local(struct register_desc desc, uint32_t value); + +/* Floating point registers */ +static union float_value get_reg_float(struct register_desc desc); +static void set_reg_float(struct register_desc desc, union float_value value); + +static union double_value get_reg_double(struct register_desc desc); +static void set_reg_double(struct register_desc desc, union double_value value); + + +static struct register_func_standard function_handler[] = { + { "inv", none, NULL, NULL }, + { "psr", standard_reg, &get_reg_psr, &set_reg_psr }, + { "tbr", standard_reg, &get_reg_tbr, &set_reg_tbr }, + { "wim", standard_reg, &get_reg_wim, &set_reg_wim }, + { "y", standard_reg, &get_reg_y, &set_reg_y }, + { "pc", standard_reg, &get_reg_pc, &set_reg_pc }, + { "npc", standard_reg, &get_reg_npc, &set_reg_npc }, + { "fsr", standard_reg, &get_reg_fsr, &set_reg_fsr }, + { "sp", standard_reg, &get_reg_sp, &set_reg_sp }, + { "fp", standard_reg, &get_reg_fp, &set_reg_fp }, + { "g", standard_reg, &get_reg_global, &set_reg_global }, + { "i", standard_reg, &get_reg_input, &set_reg_input }, + { "o", standard_reg, &get_reg_output, &set_reg_output }, + { "l", standard_reg, &get_reg_local, &set_reg_local } +}; + +static struct register_func_float function_handler_float = { "f", float_reg, &get_reg_float, &set_reg_float }; +static struct register_func_double function_handler_double = { "d", double_reg, &get_reg_double, &set_reg_double }; + + + + +struct register_desc parse_register(const char * const reg, uint32_t cpu) +{ + uint32_t param_length = strlen(reg); + + /* start name is invalid in case parsing doesn't work */ + struct register_desc desc { "inv", standard_reg, cpu, 0, dsu_get_reg_psr(cpu) & 0x1F }; + + /* Special purpose registers */ + if (strcmp(reg, "psr") == 0) { + strcpy(desc.name, "psr"); + return desc; + } + + if (strcmp(reg, "tbr") == 0) { + strcpy(desc.name, "tbr"); + return desc; + } + + if (strcmp(reg, "wim") == 0) { + strcpy(desc.name, "wim"); + return desc; + } + + if (strcmp(reg, "y") == 0) { + strcpy(desc.name, "y"); + return desc; + } + + if (strcmp(reg, "pc") == 0) { + strcpy(desc.name, "pc"); + return desc; + } + + if (strcmp(reg, "npc") == 0) { + strcpy(desc.name, "npc"); + return desc; + } + + if (strcmp(reg, "fsr") == 0) { + strcpy(desc.name, "fsr"); + return desc; + } + + if (strcmp(reg, "sp") == 0) { + strcpy(desc.name, "sp"); + return desc; + } + + if (strcmp(reg, "fp") == 0) { + strcpy(desc.name, "fp"); + return desc; + } + + /* length must be at least two from here on out */ + if (param_length < 2) + return desc; + + /* Window registers */ + switch(reg[0]) { + + case 'g': + if (param_length != 2) + return desc; + + if (parse_register_number_single(reg[1], &desc.reg_num) == -1) + return desc; + + strcpy(desc.name, "g"); + break; + + case 'i': + if (param_length != 2) + return desc; + + if (parse_register_number_single(reg[1], &desc.reg_num) == -1) + return desc; + + strcpy(desc.name, "i"); + break; + + case 'l': + if (param_length != 2) + return desc; + + if (parse_register_number_single(reg[1], &desc.reg_num) == -1) + return desc; + + strcpy(desc.name, "l"); + break; + + case 'o': + if (param_length != 2) + return desc; + + if (parse_register_number_single(reg[1], &desc.reg_num) == -1) + return desc; + + strcpy(desc.name, "o"); + break; + + case 'f': + if (param_length > 3) + return desc; + + if (parse_register_number(reg + 1, &desc.reg_num, 31) == -1) + return desc; + + desc.type = float_reg; + strcpy(desc.name, "f"); + break; + + case 'd': + if (param_length > 3) + return desc; + + if (parse_register_number(reg + 1, &desc.reg_num, 12) == -1) + return desc; + + desc.type = double_reg; + strcpy(desc.name, "d"); + break; + + case 'w': + /* TODO: needs a bit more checks here */ + if (parse_register_number_single(reg[1], &desc.window) == -1) + return desc; + + if (param_length == 2) { + strcpy(desc.name, "w"); + } else if (param_length == 4) { + if (parse_register_number_single(reg[3], &desc.reg_num) == -1) + return desc; + + desc.name[0] = reg[2]; + desc.name[1] = '\0'; + } + + break; + } + + return desc; +} + + +struct register_func *get_register_functions(const struct register_desc desc) +{ + + switch(desc.type) { + + + case standard_reg: + for (uint32_t i = 1; i < (sizeof(function_handler) / sizeof(function_handler[0])); i++) { + if (strcmp(desc.name, function_handler[i].name) == 0) + return (register_func*)&function_handler[i]; + } + + return (register_func*)&function_handler[0]; + + break; + + case float_reg: + return (register_func*)&function_handler_float; + break; + + case double_reg: + return (register_func*)&function_handler_double; + break; + + case none: + return (register_func*)&function_handler[0]; + break; + } + + /* should never reach here, but removes warning */ + return (register_func*)&function_handler[0]; +} + + +void register_print_summary(uint32_t cpu, uint32_t cwp) +{ + uint32_t ins[8], locals[8], outs[8], globals[8]; + + dsu_get_input_reg_window(cpu, cwp, ins); + dsu_get_local_reg_window(cpu, cwp, locals); + dsu_get_output_reg_window(cpu, cwp, outs); + dsu_get_global_reg(cpu, globals); + + printf(" %-8s %-8s %-8s %-8s\n", "INS", "LOCALS", "OUTS", "GLOBALS"); + + for(uint32_t i = 0; i < 8; i++) { + printf("%6d: %08X %08X %08X %08X\n", i, ins[i], locals[i], outs[i], globals[i]); + } + printf("\n"); + + printf(" psr: %08X wim: %08X tbr: %08X y: %08X\n\n", + dsu_get_reg_psr(cpu), dsu_get_reg_wim(cpu), + dsu_get_reg_tbr(cpu), dsu_get_reg_y(cpu)); + + printf(" pc: %08X\n", dsu_get_reg_pc(cpu)); + printf(" npc: %08X\n", dsu_get_reg_npc(cpu)); + printf("\n\n\n"); +} + + +static int parse_register_number_single(const char reg_num, uint32_t *dest) +{ + if (reg_num < '0' || reg_num > '7') + return -1; + + *dest = reg_num - '0'; + return 0; +} + +static int parse_register_number(const char * const reg, uint32_t * const reg_num, uint32_t highest_register) +{ + uint32_t len = strlen(reg); + + *reg_num = 0; + + if (len > 4) + return -1; + + for(uint32_t i = 1; i < len; i++) { + if (reg[i] < '0' || reg[i] > '9') + return -1; + + *reg_num += (reg[i] - '0') * 10; + } + + *reg_num = *reg_num / 10; + + if (*reg_num > highest_register) + return -1; + else + return 0; +} + + +/* Special purpose registers */ + +static uint32_t get_reg_psr(struct register_desc desc) +{ + return dsu_get_reg_psr(desc.cpu); +} + + +static void set_reg_psr(struct register_desc desc, uint32_t value) +{ + dsu_set_reg_psr(desc.cpu, value); +} + +static uint32_t get_reg_tbr(struct register_desc desc) +{ + return dsu_get_reg_tbr(desc.cpu); +} + + +static void set_reg_tbr(struct register_desc desc, uint32_t value) +{ + dsu_set_reg_tbr(desc.cpu, value); +} + +static uint32_t get_reg_wim(struct register_desc desc) +{ + return dsu_get_reg_wim(desc.cpu); +} + + +static void set_reg_wim(struct register_desc desc, uint32_t value) +{ + dsu_set_reg_wim(desc.cpu, value); +} + +static uint32_t get_reg_y(struct register_desc desc) +{ + return dsu_get_reg_y(desc.cpu); +} + + +static void set_reg_y(struct register_desc desc, uint32_t value) +{ + dsu_set_reg_y(desc.cpu, value); +} + +static uint32_t get_reg_pc(struct register_desc desc) +{ + return dsu_get_reg_pc(desc.cpu); +} + + +static void set_reg_pc(struct register_desc desc, uint32_t value) +{ + dsu_set_reg_pc(desc.cpu, value); +} + +static uint32_t get_reg_npc(struct register_desc desc) +{ + return dsu_get_reg_npc(desc.cpu); +} + + +static void set_reg_npc(struct register_desc desc, uint32_t value) +{ + dsu_set_reg_npc(desc.cpu, value); +} + +static uint32_t get_reg_fsr(struct register_desc desc) +{ + return dsu_get_reg_fsr(desc.cpu); +} + + +static void set_reg_fsr(struct register_desc desc, uint32_t value) +{ + dsu_set_reg_fsr(desc.cpu, value); +} + + +static uint32_t get_reg_sp(struct register_desc desc) +{ + return dsu_get_reg_sp(desc.cpu, desc.window); +} + + +static void set_reg_sp(struct register_desc desc, uint32_t value) +{ + dsu_set_reg_sp(desc.cpu, desc.window, value); +} + +static uint32_t get_reg_fp(struct register_desc desc) +{ + return dsu_get_reg_fp(desc.cpu, desc.window); +} + + +static void set_reg_fp(struct register_desc desc, uint32_t value) +{ + dsu_set_reg_fp(desc.cpu, desc.window, value); +} + +/* Window register */ +static uint32_t get_reg_global(struct register_desc desc) +{ + return dsu_get_global_reg(desc.cpu, desc.reg_num); +} + +static void set_reg_global(struct register_desc desc, uint32_t value) +{ + dsu_set_global_reg(desc.cpu, desc.reg_num, value); +} + + +static uint32_t get_reg_input(struct register_desc desc) +{ + return dsu_get_input_reg_single(desc.cpu, desc.window, desc.reg_num); +} + +static void set_reg_input(struct register_desc desc, uint32_t value) +{ + dsu_set_input_reg(desc.cpu, desc.window, desc.reg_num, value); +} + + +static uint32_t get_reg_output(struct register_desc desc) +{ + return dsu_get_output_reg_single(desc.cpu, desc.window, desc.reg_num); +} + + +static void set_reg_output(struct register_desc desc, uint32_t value) +{ + dsu_set_output_reg(desc.cpu, desc.window, desc.reg_num, value); +} + +static uint32_t get_reg_local(struct register_desc desc) +{ + return dsu_get_local_reg_single(desc.cpu, desc.window, desc.reg_num); +} + +static void set_reg_local(struct register_desc desc, uint32_t value) +{ + dsu_set_local_reg(desc.cpu, desc.window, desc.reg_num, value); +} + +/* Floating point register */ + +static union float_value get_reg_float(struct register_desc desc) +{ + return dsu_get_float_reg(desc.cpu, desc.reg_num); +} + +static void set_reg_float(struct register_desc desc, union float_value value) +{ + dsu_set_float_reg(desc.cpu, desc.reg_num, value); +} + + +static union double_value get_reg_double(struct register_desc desc) +{ + return dsu_get_double_reg(desc.cpu, desc.reg_num); +} + +static void set_reg_double(struct register_desc desc, union double_value value) +{ + dsu_set_double_reg(desc.cpu, desc.reg_num, value); +} diff --git a/src/uviemon_reg.h b/src/uviemon_reg.h new file mode 100644 index 0000000000000000000000000000000000000000..4f56287e9c7d02f8387eddc96c79e03d39fe301f --- /dev/null +++ b/src/uviemon_reg.h @@ -0,0 +1,56 @@ +#ifndef UVIEMON_REG_H +#define UVIEMON_REG_H + + +#include "leon3_dsu.h" + +enum register_type { + none, standard_reg, float_reg, double_reg +}; + +struct register_desc { + char name[4]; + enum register_type type; + uint32_t cpu; + uint32_t reg_num; + uint32_t window; + +}; + + +struct register_func { + char name[4]; + enum register_type type; +}; + +struct register_func_standard { + char name[4]; + enum register_type type; + uint32_t (*get_value)(struct register_desc); + void (*set_value)(struct register_desc, uint32_t value); +}; + +struct register_func_float { + char name[4]; + enum register_type type; + union float_value (*get_value)(struct register_desc); + void (*set_value)(struct register_desc, union float_value value); +}; + +struct register_func_double { + char name[4]; + enum register_type type; + union double_value (*get_value)(struct register_desc); + void (*set_value)(struct register_desc, union double_value value); +}; + + + + +void register_print_summary(uint32_t cpu, uint32_t cwp); + +struct register_desc parse_register(const char * const reg, uint32_t cpu); +struct register_func *get_register_functions(const struct register_desc desc); + + +#endif