/* Displays contents of ".COD" files
Copyright 2001-2005 Scott Dattalo
Copyright 2012 Borut Ražem
Copyright 2016 Molnár Károly
*/
#include "stdhdr.h"
#include "libgputils.h"
#include "gpvc.h"
#include "dump.h"
#include "block.h"
#define MAX_SOURCE_FILES 100
typedef struct memmap_info {
unsigned start_addr;
unsigned end_addr;
struct memmap_info *next;
} memmap_info_t;
static uint8_t cod_block[COD_BLOCK_SIZE];
static bool used_map[COD_BLOCK_SIZE];
static unsigned number_of_source_files = 0;
static char *source_file_names[MAX_SOURCE_FILES] = { NULL, };
static FILE *source_files[MAX_SOURCE_FILES] = { NULL, };
static const char *symbol_type_str[] = {
"a_reg" , "x_reg" , "c_short" , "c_long" , /* 0 - 3 */
"c_ushort" , "c_ulong" , "c_pointer" , "c_upointer" , /* 4 - 7 */
"table" , "m_byte" , "m_boolean" , "m_index" , /* 8 - 11 */
"byte_array" , "u_byte_array" , "word_array" , "u_word_array" , /* 12 - 15 */
"func_void_none" , "func_void_byte" , "func_void_twobyte", "func_void_long" , /* 16 - 19 */
"func_void_undef" , "func_int_none" , "func_int_byte" , "func_int_twobyte" , /* 20 - 23 */
"func_int_long" , "func_int_undef" , "func_long_none" , "func_long_byte" , /* 24 - 27 */
"func_long_twobyte", "func_long_long" , "func_long_undef" , "pfunc_void_none" , /* 28 - 31 */
"pfunc_void_byte" , "pfunc_void_twobyte", "pfunc_void_long" , "pfunc_void_undef" , /* 32 - 35 */
"pfunc_int_none" , "pfunc_int_byte" , "pfunc_int_twobyte", "pfunc_int_long" , /* 36 - 39 */
"pfunc_int_undef" , "pfunc_long_none" , "pfunc_long_byte" , "pfunc_long_twobyte", /* 40 - 43 */
"pfunc_long_long" , "pfunc_long_undef" , "address" , "constant" , /* 44 - 47 */
"bad_und" , "br_und" , "upper_und" , "byte_und" , /* 48 - 51 */
"add_und" , "m_keyword" , "add_mi_und" , "vector" , /* 52 - 55 */
"port_w" , "port_r" , "port_rw" , "port_rmw" , /* 56 - 59 */
"endif" , "exundef" , "macro_t" , "macro_s" , /* 60 - 63 */
"macro_a" , "macro_c" , "c_keyword" , "void" , /* 64 - 67 */
"c_enum" , "c_typedef1" , "c_utypedef1" , "c_typedef2" , /* 68 - 71 */
"c_utypedef2" , "cp_typedef1" , "cp_utypedef1" , "cp_typedef2" , /* 72 - 75 */
"cp_utypedef2" , "c_struct" , "i_struct" , "l_const" , /* 76 - 79 */
"s_short" , "s_ushort" , "s_long" , "s_ulong" , /* 80 - 83 */
"sa_short" , "sa_ushort" , "sa_long" , "sa_ulong" , /* 84 - 87 */
"sp_short" , "sp_ushort" , "sp_long" , "sp_ulong" , /* 88 - 91 */
"fixed_pointer" , "pointer_function" , "cc_reg" , "PtrF_void_none" , /* 92 - 95 */
"PtrF_void_byte" , "PtrF_void_twobyte" , "PtrF_void_long" , "PtrF_void_undef" , /* 96 - 99 */
"PtrF_int_none" , "PtrF_int_byte" , "PtrF_int_twobyte" , "PtrF_int_long" , /* 100 - 103 */
"PtrF_int_undef" , "PtrF_long_none" , "PtrF_long_byte" , "PtrF_long_twobyte" , /* 104 - 107 */
"PtrF_long_long" , "PtrF_long_undef" , "PfAR_void_none" , "PfAR_void_byte" , /* 108 - 111 */
"PfAR_void_twobyte", "PfAR_void_long" , "PfAR_void_undef" , "PfAR_int_none" , /* 112 - 115 */
"PfAR_int_byte" , "PfAR_int_twobyte" , "PfAR_int_long" , "PfAR_int_undef" , /* 116 - 119 */
"PfAR_long_none" , "PfAR_long_byte" , "PfAR_long_twobyte", "PfAR_long_long" , /* 120 - 123 */
"PfAR_long_undef" , "FWDlit" , "Pfunc" , "mgoto" , /* 124 - 127 */
"mcgoto" , "mcgoto2" , "mcgoto3" , "mcgoto4" , /* 128 - 131 */
"mcgoto74" , "mcgoto17" , "mccall17" , "mcall" , /* 132 - 135 */
"mc_call" , "res_word" , "local" , "unknown" , /* 136 - 139 */
"varlabel" , "external" , "global" , "segment" , /* 140 - 143 */
"bank_addr" , "bit_0" , "bit_1" , "bit_2" , /* 144 - 147 */
"bit_3" , "bit_4" , "bit_5" , "bit_6" , /* 148 - 151 */
"bit_7" , "debug" /* 152 - 153 */
};
static memmap_info_t *memmap_info_list = NULL;
static memmap_info_t *memmap_info_list_last = NULL;
/*------------------------------------------------------------------------------------------------*/
static const char *
_symbol_type_to_str(unsigned Type)
{
static char err[64];
if (Type < ARRAY_SIZE(symbol_type_str)) {
return symbol_type_str[Type];
}
snprintf(err, sizeof(err), "invalid type: %u", Type);
return err;
}
/*------------------------------------------------------------------------------------------------*/
void _memmap_add(unsigned Start_addr, unsigned End_addr) {
memmap_info_t*pnew = new memmap_info_t;
memset(pnew,0,sizeof*pnew);
pnew->start_addr = Start_addr;
pnew->end_addr = End_addr;
if (!memmap_info_list) {
/* The list is empty. */
memmap_info_list = pnew;
}else{
/* Append the pnew node to the end of the list. */
memmap_info_list_last->next = pnew;
}
memmap_info_list_last = pnew;
}
/*------------------------------------------------------------------------------------------------*/
static void _memmap_free() {
memmap_info_t *info;
memmap_info_t *next;
info = memmap_info_list;
while (info) {
next = info->next;
free(info);
info = next;
}
memmap_info_list = NULL;
memmap_info_list_last = NULL;
}
/*------------------------------------------------------------------------------------------------*/
static void _memmap_create_used_map(unsigned Start_address) {
const memmap_info_t *info;
unsigned block_start;
unsigned block_end;
unsigned offset;
unsigned size;
info = memmap_info_list;
if (!info) {
memset(used_map, true, sizeof(used_map));
return;
}
memset(used_map, false, sizeof(used_map));
block_start = (Start_address / COD_BLOCK_SIZE) * COD_BLOCK_SIZE;
block_end = block_start + COD_BLOCK_SIZE;
while (info) {
if ((info->start_addr >= block_start) && (info->start_addr < block_end)) {
offset = info->start_addr - block_start;
size = info->end_addr - info->start_addr;
if ((offset + size) > COD_BLOCK_SIZE) {
size = COD_BLOCK_SIZE - offset;
}
if (size > 0) {
/* This is a used ROM range. */
memset(used_map+offset, true, size);
}
}else if (info->start_addr < block_start && info->start_addr < block_end) {
size = info->end_addr - block_start;
if (size > COD_BLOCK_SIZE) size = COD_BLOCK_SIZE;
if (size > 0) {
/* This is a used ROM range. */
memset(used_map, true, size);
}
}else if (info->start_addr >= block_end) {
/* The further values will be too high. */
break;
}
info = info->next;
}
}
/*------------------------------------------------------------------------------------------------*/
/*
_fget_line - read a line from a file.
*/
static char* _fget_line(int Line, char *Buffer, int Size, FILE *pFile) {
static FILE *plastFile = NULL;
static int lastline = -1;
static long lastPos = -1;
char *ps;
if (pFile == NULL) {
return NULL;
}
/*
If we read a line from the same file the last time we were called
then see if we can take advantage of the file state:
*/
if ((pFile != plastFile) || /* if the file is the same */
(Line < (lastline - 1)) || /* and the line is past the previous */
(ftell(pFile) != lastPos)) { /* and the file hasn't been touched */
plastFile = pFile;
lastline = 1;
lastPos = -1;
rewind(pFile);
}
while (Line >= ++lastline) {
ps = fgets(Buffer, Size, plastFile);
assert(ps == Buffer);
}
ps = fgets(Buffer, Size, plastFile);
assert(ps == Buffer);
lastPos = ftell(plastFile);
return Buffer;
}
/*------------------------------------------------------------------------------------------------*/
/*
* Dump directory block.
*/
static void _dump_directory_block(const uint8_t *Cblock, unsigned Block_num) {
char temp_buf[256];
unsigned year;
char month[8];
unsigned day;
unsigned time;
unsigned bytes_for_address;
#if defined(HAVE_LOCALE_H) && defined(HAVE_LANGINFO_H)
struct tm tm;
#endif
/* Pascal style string. */
gp_str_from_Pstr(temp_buf, sizeof(temp_buf), &Cblock[COD_DIR_DATE], COD_DIR_DATE_SIZE, NULL);
time = gp_getl16(&Cblock[COD_DIR_TIME]);
sscanf(temp_buf, "%u%3s%u", &day, month, &year);
#if defined(HAVE_LOCALE_H) && defined(HAVE_LANGINFO_H)
memset(&tm, 0, sizeof(tm));
snprintf(temp_buf, sizeof(temp_buf), "%u %s %u %u %u", year + 2000, month, day, time / 100, time % 100);
strptime(temp_buf, "%Y %b %d %H %M", &tm);
setlocale(LC_ALL, "");
#endif
printf("Directory block: %04x\n"
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", Block_num);
/* Pascal style string. */
printf("%03x - Source file: %s\n",
COD_DIR_SOURCE,
gp_str_from_Pstr(temp_buf, sizeof(temp_buf), &Cblock[COD_DIR_SOURCE], COD_DIR_SOURCE_SIZE, NULL));
#if defined(HAVE_LOCALE_H) && defined(HAVE_LANGINFO_H)
strftime(temp_buf, sizeof(temp_buf), nl_langinfo(D_FMT), &tm);
printf("%03x - Date: %s\n",
COD_DIR_DATE, temp_buf);
#else
printf("%03x - Date: %u %s %u\n",
COD_DIR_DATE, day, month, year + 2000);
#endif
#if defined(HAVE_LOCALE_H) && defined(HAVE_LANGINFO_H)
strftime(temp_buf, sizeof(temp_buf), nl_langinfo(T_FMT), &tm);
setlocale(LC_ALL, "C");
printf("%03x - Time: %s\n",
COD_DIR_TIME, temp_buf);
#else
printf("%03x - Time: %02u:%02u\n",
COD_DIR_TIME, time / 100, time % 100);
#endif
/* Pascal style string. */
printf("%03x - Compiler version: %s\n",
COD_DIR_VERSION,
gp_str_from_Pstr(temp_buf, sizeof(temp_buf), &Cblock[COD_DIR_VERSION], COD_DIR_VERSION_SIZE, NULL));
/* Pascal style string. */
printf("%03x - Compiler: %s\n",
COD_DIR_COMPILER,
gp_str_from_Pstr(temp_buf, sizeof(temp_buf), &Cblock[COD_DIR_COMPILER], COD_DIR_COMPILER_SIZE, NULL));
/* Pascal style string. */
printf("%03x - Notice: %s\n",
COD_DIR_NOTICE,
gp_str_from_Pstr(temp_buf, sizeof(temp_buf), &Cblock[COD_DIR_NOTICE], COD_DIR_NOTICE_SIZE, NULL));
bytes_for_address = Cblock[COD_DIR_ADDRSIZE];
printf("%03x - Bytes for address: %u\n", COD_DIR_ADDRSIZE, bytes_for_address);
if (bytes_for_address != 0) {
printf("WARNING: Address size looks suspicious.\n");
}
printf("%03x - High word of 64k address: %04x\n",
COD_DIR_HIGHADDR, gp_getl16(&Cblock[COD_DIR_HIGHADDR]));
printf("%03x - Next directory block: %04x\n",
COD_DIR_NEXTDIR, gp_getl16(&Cblock[COD_DIR_NEXTDIR]));
printf("%03x - COD file version: %d\n",
COD_DIR_CODTYPE, gp_getl16(&Cblock[COD_DIR_CODTYPE]));
/* Pascal style string. */
printf("%03x - Processor: %s\n",
COD_DIR_PROCESSOR,
gp_str_from_Pstr(temp_buf, sizeof(temp_buf), &Cblock[COD_DIR_PROCESSOR], COD_DIR_PROCESSOR_SIZE, NULL));
printf("%03x,%03x - Short symbol table start block: %04x end block: %04x\n",
COD_DIR_SYMTAB, COD_DIR_SYMTAB + 2,
gp_getl16(&Cblock[COD_DIR_SYMTAB]),
gp_getl16(&Cblock[COD_DIR_SYMTAB + 2]));
printf("%03x,%03x - File name table start block: %04x end block: %04x\n",
COD_DIR_NAMTAB, COD_DIR_NAMTAB + 2,
gp_getl16(&Cblock[COD_DIR_NAMTAB]),
gp_getl16(&Cblock[COD_DIR_NAMTAB + 2]));
printf("%03x,%03x - Source info table start block: %04x end block: %04x\n",
COD_DIR_LSTTAB, COD_DIR_LSTTAB + 2,
gp_getl16(&Cblock[COD_DIR_LSTTAB]),
gp_getl16(&Cblock[COD_DIR_LSTTAB + 2]));
printf("%03x,%03x - Rom table start block: %04x end block: %04x\n",
COD_DIR_MEMMAP, COD_DIR_MEMMAP + 2,
gp_getl16(&Cblock[COD_DIR_MEMMAP]),
gp_getl16(&Cblock[COD_DIR_MEMMAP + 2]));
printf("%03x,%03x - Local scope table start block: %04x end block: %04x\n",
COD_DIR_LOCALVAR, COD_DIR_LOCALVAR + 2,
gp_getl16(&Cblock[COD_DIR_LOCALVAR]),
gp_getl16(&Cblock[COD_DIR_LOCALVAR + 2]));
printf("%03x,%03x - Long symbol table start block: %04x end block: %04x\n",
COD_DIR_LSYMTAB, COD_DIR_LSYMTAB + 2,
gp_getl16(&Cblock[COD_DIR_LSYMTAB]),
gp_getl16(&Cblock[COD_DIR_LSYMTAB + 2]));
printf("%03x,%03x - Debug messages start block: %04x end block: %04x\n",
COD_DIR_MESSTAB, COD_DIR_MESSTAB + 2,
gp_getl16(&Cblock[COD_DIR_MESSTAB]),
gp_getl16(&Cblock[COD_DIR_MESSTAB + 2]));
putchar('\n');
}
/*------------------------------------------------------------------------------------------------*/
/*
* Dump directory block code index.
*/
static void _dump_index(proc_class_t Class, const uint8_t *Cblock) {
unsigned _64k_base;
unsigned i;
unsigned curr_block;
int addr_digits;
printf("Code blocks index:\n"
"Block range Block number\n"
"---------------------------\n");
_64k_base = IMemAddrFromBase((unsigned)gp_getu16(&Cblock[COD_DIR_HIGHADDR]));
addr_digits = Class->addr_digits;
for (i = 0; i < COD_CODE_IMAGE_BLOCKS; ++i) {
curr_block = gp_getu16(&Cblock[i * 2]);
if (curr_block != 0) {
printf("%0*x-%0*x: %u\n",
addr_digits, _64k_base | MemOffsFromBlock(i),
addr_digits, (_64k_base | (MemOffsFromBlock(i + 1) - 1)),
curr_block);
}
}
putchar('\n');
}
/*------------------------------------------------------------------------------------------------*/
/*
* Dump directory block.
*/
void dump_directory_blocks(const DirBlockInfo *Main_dir, proc_class_t Class) {
const DirBlockInfo *dbi;
unsigned block_num;
block_num = 0;
dbi = Main_dir;
do {
_dump_directory_block(dbi->dir, block_num);
_dump_index(Class, dbi->dir);
block_num = gp_getl16(&dbi->dir[COD_DIR_NEXTDIR]);
dbi = dbi->next;
} while (dbi);
}
/*------------------------------------------------------------------------------------------------*/
/*
* ROM usage information.
*/
void dump_memmap(FILE *Code_file, const DirBlockInfo *Main_dir,
proc_class_t Class, bool Make_list) {
const DirBlockInfo *dbi;
unsigned _64k_base;
int addr_digits;
unsigned start_map_block;
unsigned end_map_block;
unsigned i;
unsigned j;
unsigned offset;
const uint8_t *record;
unsigned first_offset;
unsigned last_offset;
unsigned start_addr;
unsigned end_addr;
bool first;
first = true;
addr_digits = Class->addr_digits;
dbi = Main_dir;
do {
_64k_base = IMemAddrFromBase((unsigned)gp_getu16(&dbi->dir[COD_DIR_HIGHADDR]));
start_map_block = gp_getu16(&dbi->dir[COD_DIR_MEMMAP]);
if (start_map_block != 0) {
end_map_block = gp_getu16(&dbi->dir[COD_DIR_MEMMAP + 2]);
if (first) {
printf("ROM Usage:\n"
"----------------------------\n");
first = false;
}
for (j = start_map_block; j <= end_map_block; j++) {
read_block(Code_file, cod_block, j);
for (i = 0, offset = 0; i < COD_CODE_IMAGE_BLOCKS; offset += COD_MAPENTRY_SIZE, ++i) {
record = &cod_block[offset];
first_offset = gp_getl16(&record[COD_MAPTAB_START]);
last_offset = gp_getl16(&record[COD_MAPTAB_LAST]);
if ((first_offset != 0) || (last_offset != 0)) {
start_addr = _64k_base + first_offset;
end_addr = _64k_base + last_offset + 1;
printf("using ROM %0*x to %0*x\n",
addr_digits, gp_processor_insn_from_byte_c(Class, start_addr),
addr_digits, gp_processor_insn_from_byte_c(Class, end_addr) - 1);
if (Make_list) {
_memmap_add(start_addr, end_addr);
}
}
}
}
}
else if (first) {
printf("No ROM usage information available.\n");
}
putchar('\n');
dbi = dbi->next;
} while (dbi);
}
/*------------------------------------------------------------------------------------------------*/
static bool _is_empty_to_last(unsigned Index, unsigned End) {
while (Index < End) {
if (used_map[Index * WORD_SIZE]) {
return false;
}
++Index;
}
return true;
}
/*------------------------------------------------------------------------------------------------*/
/*
* Dump all of the machine code in the .cod file.
*/
#define CODE_COLUMN_NUM 8
#define CODE_COLUMN_NUM_WIDE 16
void dump_code(FILE *Code_file, const DirBlockInfo *Main_dir,
pic_processor_t Processor, bool Wide_dump) {
proc_class_t pclass;
char border_gap0[16];
char border_gap1[16];
char buffer[BUFSIZ];
const DirBlockInfo *dbi;
MemBlock_t *data;
int addr_digits;
unsigned _64k_base;
unsigned block_index;
unsigned byte_address;
int num_words;
unsigned bsr_boundary;
unsigned i;
unsigned j;
unsigned k;
unsigned column_num;
uint16_t word;
bool used_prev;
bool used_act;
bool empty_signal;
bool empty_line;
pclass = Processor->pclass;
dump_memmap(Code_file, Main_dir, pclass, true);
bsr_boundary = gp_processor_bsr_boundary(Processor);
addr_digits = pclass->addr_digits;
column_num = (Wide_dump) ? CODE_COLUMN_NUM_WIDE : CODE_COLUMN_NUM;
dbi = Main_dir;
i = addr_digits + 2;
j = (i < (sizeof(border_gap0) - 1)) ? i : (sizeof(border_gap0) - 1);
if (j > 0) {
memset(border_gap0, ' ', j);
}
border_gap0[j] = '\0';
j = (i < (sizeof(border_gap1) - 1)) ? i : (sizeof(border_gap1) - 1);
if (j > 0) {
memset(border_gap1, '-', j);
}
border_gap1[j] = '\0';
printf("Formatted Code Dump:\n");
do {
_64k_base = IMemAddrFromBase((unsigned)gp_getu16(&dbi->dir[COD_DIR_HIGHADDR]));
for (k = 0; k < COD_CODE_IMAGE_BLOCKS; k++) {
block_index = gp_getu16(&dbi->dir[(k + COD_DIR_CODE) * WORD_SIZE]);
if (block_index != 0) {
read_block(Code_file, cod_block, block_index);
byte_address = _64k_base + (k * COD_BLOCK_N_WORDS) * WORD_SIZE;
if (Wide_dump) {
printf("%s---------------------------------------------------------------------------------\n"
" Block %u -- %0*x-%0*x\n"
"%s+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+\n"
"%s| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f |\n"
"%s+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+\n",
border_gap1,
block_index,
addr_digits, byte_address,
addr_digits, byte_address + COD_BLOCK_SIZE - 1,
border_gap1,
border_gap0,
border_gap1);
}
else {
printf("%s-----------------------------------------\n"
" Block %u -- %0*x-%0*x\n"
"%s+----+----+----+----+----+----+----+----+\n"
"%s| 0;8| 1;9| 2;a| 3;b| 4;c| 5;d| 6;e| 7;f|\n"
"%s+----+----+----+----+----+----+----+----+\n",
border_gap1,
block_index,
addr_digits, byte_address,
addr_digits, byte_address + COD_BLOCK_SIZE - 1,
border_gap1,
border_gap0,
border_gap1);
}
_memmap_create_used_map(byte_address);
/* Shows the COD block. */
if (memmap_info_list) {
/* Use the informations of memory map. */
i = 0;
do {
empty_line = true;
for (j = 0; j < column_num; j++) {
if (used_map[(i + j) * WORD_SIZE]) {
empty_line = false;
break;
}
}
if (! empty_line) {
byte_address = _64k_base + (k * COD_BLOCK_N_WORDS + i) * WORD_SIZE;
printf("%0*x: ", addr_digits, gp_processor_insn_from_byte_c(pclass, byte_address));
for (j = 0; j < column_num; j++) {
if (used_map[(i + j) * WORD_SIZE]) {
/* This is a used ROM word. */
printf(" %04x", gp_getu16(&cod_block[(i + j) * WORD_SIZE]));
}
else if (!_is_empty_to_last(i + j, i + column_num)) {
/* In this line there is also at least one used ROM word. */
printf(" ....");
}
else {
/* Sooner ends the line. */
break;
}
}
putchar('\n');
}
i += column_num;
} while (i < COD_BLOCK_N_WORDS);
}
else {
/* No memory map. */
i = 0;
do {
empty_line = true;
for (j = 0; j < column_num; j++) {
if (gp_getu16(&cod_block[(i + j) * WORD_SIZE]) != 0) {
empty_line = false;
break;
}
}
if (! empty_line) {
byte_address = _64k_base + (k * COD_BLOCK_N_WORDS + i) * WORD_SIZE;
printf("%0*x: ", addr_digits, gp_processor_insn_from_byte_c(pclass, byte_address));
for (j = 0; j < column_num; j++) {
printf(" %04x", gp_getu16(&cod_block[(i + j) * WORD_SIZE]));
}
putchar('\n');
}
i += column_num;
} while (i < COD_BLOCK_N_WORDS);
}
putchar('\n');
/* Create the instruction memory and populates from COD block. */
byte_address = _64k_base + k * COD_BLOCK_N_WORDS * WORD_SIZE;
data = gp_mem_i_create();
for (j = 0; j < COD_BLOCK_SIZE; j++) {
gp_mem_b_put(data, byte_address + j, cod_block[j], NULL, NULL);
}
/* Disassembles this code array. */
i = 0;
used_prev = false;
empty_signal = false;
do {
num_words = 1;
used_act = used_map[i * WORD_SIZE];
if (used_act) {
if (empty_signal) {
/* This is a previous empty block. */
printf(" . . . . . . . . . . .\n");
empty_signal = false;
}
if (pclass->i_memory_get(data, byte_address, &word, NULL, NULL) != W_USED_ALL) {
/* Internal memory handling error. */
assert(0);
}
num_words = gp_disassemble(data, byte_address, pclass, bsr_boundary, 0,
GPDIS_SHOW_ALL_BRANCH, buffer, sizeof(buffer), 0);
printf("%0*x: %04x %s\n", addr_digits, gp_processor_insn_from_byte_c(pclass, byte_address), word, buffer);
if (num_words != 1) {
if (pclass->i_memory_get(data, byte_address + WORD_SIZE, &word, NULL, NULL) != W_USED_ALL) {
/* Internal memory handling error. */
assert(0);
}
printf("%0*x: %04x\n", addr_digits, gp_processor_insn_from_byte_c(pclass, byte_address + WORD_SIZE), word);
}
empty_signal = false;
}
else if (used_prev && (!used_act)) {
empty_signal = true;
}
used_prev = used_act;
byte_address += num_words * WORD_SIZE;
i += num_words;
} while (i < COD_BLOCK_N_WORDS);
gp_mem_i_free(data);
} /* if (block_index != 0) */
} /* for (k = 0; k < COD_CODE_IMAGE_BLOCKS; k++) */
dbi = dbi->next;
} while (dbi);
putchar('\n');
_memmap_free();
}
/*------------------------------------------------------------------------------------------------*/
/*
* Dump all of the (short) Symbol Table stuff in the .cod file.
*/
void dump_symbols(FILE *Code_file, const DirBlockInfo *Main_dir) {
unsigned start_block;
unsigned end_block;
unsigned i;
unsigned j;
unsigned offset;
const uint8_t *record;
unsigned length;
char name[COD_SSYMBOL_NAME_LENGTH + 1];
unsigned type;
unsigned value;
start_block = gp_getu16(&Main_dir->dir[COD_DIR_SYMTAB]);
if (start_block != 0) {
end_block = gp_getu16(&Main_dir->dir[COD_DIR_SYMTAB + 2]);
printf("Symbol Table Information:\n"
"-------------------------\n");
for (j = start_block; j <= end_block; j++) {
read_block(Code_file, cod_block, j);
for (i = 0, offset = 0; i < SYMBOLS_PER_BLOCK; offset += SSYMBOL_SIZE, ++i) {
record = &cod_block[offset];
length = record[COD_SSYMBOL_NAME];
if (length != 0) {
gp_str_from_Pstr(name, sizeof(name), &record[COD_SSYMBOL_NAME], COD_SSYMBOL_NAME_SIZE, NULL);
type = record[COD_SSYMBOL_STYPE];
value = gp_getu16(&record[COD_SSYMBOL_SVALUE]);
printf("%-12s = %04x (%6d), type = %s\n", name, value, value, _symbol_type_to_str(type));
}
}
}
}
else {
printf("No symbol table info.\n");
}
putchar('\n');
}
/*------------------------------------------------------------------------------------------------*/
static unsigned _lsymbols_max_length(FILE *Code_file, const DirBlockInfo *Main_dir) {
unsigned start_block;
unsigned end_block;
unsigned i;
unsigned j;
unsigned length;
unsigned max_length;
max_length = 0;
start_block = gp_getu16(&Main_dir->dir[COD_DIR_LSYMTAB]);
if (start_block != 0) {
end_block = gp_getu16(&Main_dir->dir[COD_DIR_LSYMTAB + 2]);
max_length = 0;
for (j = start_block; j <= end_block; j++) {
read_block(Code_file, cod_block, j);
for (i = 0; i < COD_BLOCK_SIZE; ) {
/* Pascal style string. */
length = cod_block[i];
if (length == 0) {
break;
}
if (max_length < length) {
max_length = length;
}
i += length + COD_LSYMBOL_EXTRA;
}
}
}
return max_length;
}
/*------------------------------------------------------------------------------------------------*/
/*
* Dump all of the Long Symbol Table stuff in the .cod file.
*/
void dump_lsymbols(FILE *Code_file, const DirBlockInfo *Main_dir) {
unsigned start_block;
unsigned end_block;
unsigned i;
unsigned j;
const uint8_t *sym;
unsigned length;
char name[COD_LSYMBOL_NAME_MAX_LENGTH + 1];
unsigned type;
unsigned value;
int symbol_align;
symbol_align = _lsymbols_max_length(Code_file, Main_dir);
start_block = gp_getu16(&Main_dir->dir[COD_DIR_LSYMTAB]);
if (start_block != 0) {
end_block = gp_getu16(&Main_dir->dir[COD_DIR_LSYMTAB + 2]);
printf("Long Symbol Table Information:\n"
"------------------------------------------------------------------------\n");
for (j = start_block; j <= end_block; j++) {
read_block(Code_file, cod_block, j);
for (i = 0; i < COD_BLOCK_SIZE; ) {
/* Pascal style string. */
sym = &cod_block[i + COD_LSYMBOL_NAME];
length = *sym;
if (length == 0) {
break;
}
gp_str_from_Pstr(name, sizeof(name), sym, COD_LSYMBOL_NAME_MAX_SIZE, NULL);
type = gp_getu16(&sym[length + COD_LSYMBOL_TYPE]);
/* read big endian */
value = gp_getb32(&sym[length + COD_LSYMBOL_VALUE]);
printf("%-*s = %08x (%11d), type = %s\n", symbol_align, name, value, value, _symbol_type_to_str(type));
i += length + COD_LSYMBOL_EXTRA;
}
}
}
else {
printf("No long symbol table info.\n");
}
putchar('\n');
}
/*------------------------------------------------------------------------------------------------*/
/*
* Source files.
*/
void dump_source_files(FILE *Code_file, const DirBlockInfo *Main_dir) {
unsigned start_block;
unsigned end_block;
unsigned i;
unsigned offset;
unsigned length;
char name_str[COD_FILE_NAME_LENGTH + 1];
char *name;
start_block = gp_getu16(&Main_dir->dir[COD_DIR_NAMTAB]);
if (start_block != 0) {
end_block = gp_getu16(&Main_dir->dir[COD_DIR_NAMTAB + 2]);
printf("Source File Information:\n"
"------------------------\n");
for (i = start_block; i <= end_block; ++i) {
read_block(Code_file, cod_block, i);
for (offset = 0; offset < COD_BLOCK_SIZE; ) {
length = cod_block[offset];
if (length > 0) {
gp_str_from_Pstr(name_str, sizeof(name_str), &cod_block[offset], COD_FILE_NAME_SIZE, NULL);
name = GP_Strdup(name_str);
source_file_names[number_of_source_files] = name;
printf("%s\n", name);
source_files[number_of_source_files] = fopen(name, "rt");
number_of_source_files++;
if (number_of_source_files >= MAX_SOURCE_FILES) {
fprintf(stderr, "Too many source files, increase MAX_SOURCE_FILES and recompile the program.\n");
exit(1);
}
/* In this way will find the shorter (64 bytes length) names also. */
length += COD_SHORT_FILE_NAME_SIZE - 1;
length /= COD_SHORT_FILE_NAME_SIZE;
length *= COD_SHORT_FILE_NAME_SIZE;
offset += length;
}
else {
offset += COD_SHORT_FILE_NAME_SIZE;
}
}
}
}
else {
printf("No source file info.\n");
}
putchar('\n');
}
/*------------------------------------------------------------------------------------------------*/
static const char* _mod_flags_to_str(int Mode) {
static char fl[9];
fl[0] = (Mode & COD_LS_SMOD_FLAG_C1) ? 'C' : '.';
fl[1] = (Mode & COD_LS_SMOD_FLAG_F) ? 'F' : '.';
fl[2] = (Mode & COD_LS_SMOD_FLAG_I) ? 'I' : '.';
fl[3] = (Mode & COD_LS_SMOD_FLAG_D) ? 'D' : '.';
fl[4] = (Mode & COD_LS_SMOD_FLAG_C0) ? 'C' : '.';
fl[5] = (Mode & COD_LS_SMOD_FLAG_L) ? 'L' : '.';
fl[6] = (Mode & COD_LS_SMOD_FLAG_N) ? 'N' : '.';
fl[7] = (Mode & COD_LS_SMOD_FLAG_A) ? 'A' : '.';
fl[8] = '\0';
return fl;
}
/*------------------------------------------------------------------------------------------------*/
/*
* Line number info from the source files.
*/
void dump_line_symbols(FILE *Code_file, const DirBlockInfo *Main_dir) {
static unsigned lst_line_number = 1;
static unsigned last_src_line = 0;
char line[2048];
char nbuf[128];
const char *source_file_name;
const DirBlockInfo *dbi;
bool has_line_num_info;
unsigned _64k_base;
unsigned start_block;
unsigned end_block;
unsigned i;
unsigned j;
unsigned offset;
const uint8_t *record;
unsigned src_file_num;
unsigned src_mod_flag;
unsigned src_line_num;
unsigned insn_offset;
unsigned _64k_seg_address;
has_line_num_info = false;
dbi = Main_dir;
while (dbi) {
_64k_base = gp_getu16(&dbi->dir[COD_DIR_HIGHADDR]);
_64k_seg_address = IMemAddrFromBase(_64k_base);
start_block = gp_getu16(&dbi->dir[COD_DIR_LSTTAB]);
if (start_block != 0) {
end_block = gp_getu16(&dbi->dir[COD_DIR_LSTTAB + 2]);
if (!has_line_num_info) {
has_line_num_info = true;
printf("Line Number Information:\n"
" LstLn SrcLn Addr Flags FileName\n"
" ----- ----- ------ ----------- ---------------------------------------------------------------\n");
}
for (j = start_block; j <= end_block; j++) {
read_block(Code_file, cod_block, j);
for (i = 0, offset = 0; i < COD_MAX_LINE_SYM; offset += COD_LINE_SYM_SIZE, ++i) {
record = &cod_block[offset];
src_file_num = record[COD_LS_SFILE];
src_mod_flag = record[COD_LS_SMOD];
src_line_num = gp_getu16(&record[COD_LS_SLINE]);
insn_offset = gp_getu16(&record[COD_LS_SLOC]);
if (((src_file_num != 0) || (src_mod_flag != 0) || (src_line_num != 0) || (insn_offset != 0)) &&
(FlagIsClr(src_mod_flag, COD_LS_SMOD_FLAG_L))) {
if (src_file_num < number_of_source_files) {
source_file_name = source_file_names[src_file_num];
}
else {
snprintf(nbuf, sizeof(nbuf), "Bad source file index: %u", src_file_num);
source_file_name = nbuf;
}
if ((source_file_name) && (source_file_name[0] != '\0')) {
printf(" %5u %5u %06x %2x %s %s\n",
lst_line_number, src_line_num, _64k_seg_address | insn_offset,
src_mod_flag, _mod_flags_to_str(src_mod_flag), source_file_name);
}
else {
printf(" %5u %5u %06x %2x %s\n",
lst_line_number, src_line_num, _64k_seg_address | insn_offset,
src_mod_flag, _mod_flags_to_str(src_mod_flag));
}
lst_line_number++;
if ((src_file_num < number_of_source_files) && (src_line_num != last_src_line)) {
if (source_files[src_file_num]) {
_fget_line(src_line_num, line, sizeof(line), source_files[src_file_num]);
printf("%s", line);
}
else {
printf("ERROR: Source file \"%s\" does not exist.\n", source_file_names[src_file_num]);
}
}
}
last_src_line = src_line_num;
} /* for (i = 0, offset = 0; i < COD_MAX_LINE_SYM; ... */
} /* for (j = start_block; j <= end_block; j++) */
} /* if (start_block != 0) */
dbi = dbi->next;
} /* while (dbi) */
if (!has_line_num_info) {
printf("No line number info.\n");
}
putchar('\n');
}
/*------------------------------------------------------------------------------------------------*/
/*
* Debug Message area.
*/
void dump_debug_message_area(FILE *Code_file, const DirBlockInfo *Main_dir) {
unsigned start_block;
unsigned end_block;
unsigned i;
unsigned j;
const uint8_t *record;
unsigned address;
char type;
unsigned length;
char message[COD_DEBUG_MSG_MAX_LENGTH + 1];
start_block = gp_getu16(&Main_dir->dir[COD_DIR_MESSTAB]);
if (start_block != 0) {
end_block = gp_getu16(&Main_dir->dir[COD_DIR_MESSTAB + 2]);
printf("Debug Message area:\n"
" Addr Cmd Message\n"
" -------- --- -------------------------------------\n");
for (i = start_block; i <= end_block; i++) {
read_block(Code_file, cod_block, i);
for (j = 0; j < (COD_BLOCK_SIZE - COD_DEBUG_MIN_SIZE); ) {
/* read big endian */
record = &cod_block[j];
address = gp_getb32(&record[COD_DEBUG_ADDR]);
type = record[COD_DEBUG_CMD];
if (type == '\0') {
break;
}
/* Pascal style string. */
length = record[COD_DEBUG_MSG];
gp_str_from_Pstr(message, sizeof(message), &record[COD_DEBUG_MSG], COD_DEBUG_MSG_MAX_SIZE, NULL);
printf(" %8x %c %s\n", address, type, message);
j += length + COD_DEBUG_EXTRA;
} /* for (j = 0; ... */
} /* for (i = start_block; ... */
}
else {
printf("No Debug Message information available.\n");
}
putchar('\n');
}
/*------------------------------------------------------------------------------------------------*/
/*
* Display the local symbol table information.
*/
void dump_local_vars(FILE *Code_file, const DirBlockInfo *Main_dir, proc_class_t Class) {
unsigned start_block;
unsigned end_block;
unsigned i;
unsigned j;
unsigned offset;
const uint8_t *record;
unsigned length;
unsigned start;
unsigned stop;
char name[COD_SSYMBOL_NAME_LENGTH + 1];
unsigned type;
unsigned value;
start_block = gp_getu16(&Main_dir->dir[COD_DIR_LOCALVAR]);
if (start_block != 0) {
end_block = gp_getu16(&Main_dir->dir[COD_DIR_LOCALVAR + 2]);
printf("Local Symbol Scoping Information:\n"
"---------------------------------\n");
for (i = start_block; i <= end_block; i++) {
read_block(Code_file, cod_block, i);
for (j = 0, offset = 0; j < SYMBOLS_PER_BLOCK; offset += SSYMBOL_SIZE, ++j) {
record = &cod_block[offset];
length = record[COD_SSYMBOL_NAME];
if (length != 0) {
if (memcmp(&record[COD_SSYMBOL_NAME + 1], "__LOCAL", length) == 0) {
start = gp_getl32(&record[COD_SSYMBOL_START]);
stop = gp_getl32(&record[COD_SSYMBOL_STOP]);
printf("Local symbols between %06x and %06x: ",
gp_processor_insn_from_byte_c(Class, start),
gp_processor_insn_from_byte_c(Class, stop + 1) - 1);
}
else {
gp_str_from_Pstr(name, sizeof(name), &record[COD_SSYMBOL_NAME], COD_SSYMBOL_NAME_SIZE, NULL);
type = record[COD_SSYMBOL_STYPE];
value = gp_getl16(&record[COD_SSYMBOL_SVALUE]);
printf("%-12s = %04x (%6d), type = %s\n", name, value, value, _symbol_type_to_str(type));
}
}
}
}
}
else {
printf("No local variable scoping info available.\n");
}
putchar('\n');
}
/*------------------------------------------------------------------------------------------------*/
void dump_free() {
unsigned i;
if (number_of_source_files > 0) {
for (i = 0; i < number_of_source_files; ++i) {
if (source_file_names[i]) {
free(source_file_names[i]);
source_file_names[i] = NULL;
}
if (source_files[i]) {
fclose(source_files[i]);
source_files[i] = NULL;
}
}
number_of_source_files = 0;
}
}
Detected encoding: UTF-8 | 0
|