diff options
| author | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
|---|---|---|
| committer | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
| commit | 268a53de823a6750d6256ee1fb1e7707b4b45740 (patch) | |
| tree | 42c1799a9a82b2f7d9790ee9fe181d72a7274751 /sim/ucsim/cmd.src/cmd_uc.cc | |
| download | sdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz | |
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'sim/ucsim/cmd.src/cmd_uc.cc')
| -rw-r--r-- | sim/ucsim/cmd.src/cmd_uc.cc | 861 |
1 files changed, 861 insertions, 0 deletions
diff --git a/sim/ucsim/cmd.src/cmd_uc.cc b/sim/ucsim/cmd.src/cmd_uc.cc new file mode 100644 index 0000000..030d1d9 --- /dev/null +++ b/sim/ucsim/cmd.src/cmd_uc.cc @@ -0,0 +1,861 @@ +/* + * Simulator of microcontrollers (cmd.src/cmduc.cc) + * + * Copyright (C) 2001,01 Drotos Daniel, Talker Bt. + * + * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu + * + */ + +/* This file is part of microcontroller simulator: ucsim. + +UCSIM is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +UCSIM is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with UCSIM; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ +/*@1@*/ + +#include <ctype.h> + +// prj +#include "globals.h" +#include "utils.h" + +// sim.src +#include "uccl.h" + +// local, cmd.src +#include "cmd_uccl.h" + + +/* + * Command: state + *---------------------------------------------------------------------------- + */ + +//int +//cl_state_cmd::do_work(class cl_sim *sim, +// class cl_cmdline *cmdline, class cl_console *con) +COMMAND_DO_WORK_UC(cl_state_cmd) +{ + con->dd_printf("CPU state= %s PC= 0x%06x XTAL= %g\n", + get_id_string(cpu_states, uc->state), + AU(uc->PC), + uc->xtal); + con->dd_printf("Operation since last reset= (%lu vclks)\n", + (unsigned long)(uc->vc.fetch) + + (unsigned long)(uc->vc.rd) + + (unsigned long)(uc->vc.wr)); + con->dd_printf("Inst= %lu ", (unsigned long)(uc->vc.inst)); + con->dd_printf("Fetch= %lu ", (unsigned long)(uc->vc.fetch)); + con->dd_printf("Read= %lu ", (unsigned long)(uc->vc.rd)); + con->dd_printf("Write= %lu\n", (unsigned long)(uc->vc.wr)); + con->dd_printf("Total time since last reset= %g sec (%lu clks)\n", + uc->get_rtime(), (unsigned long)(uc->ticks->ticks)); + con->dd_printf("Time in isr = %g sec (%lu clks) %3.2g%%\n", + uc->isr_ticks->get_rtime(uc->xtal), + uc->isr_ticks->ticks, + (uc->ticks->ticks == 0)?0.0: + (100.0*((double)(uc->isr_ticks->ticks)/ + (double)(uc->ticks->ticks)))); + con->dd_printf("Time in idle= %g sec (%lu clks) %3.2g%%\n", + uc->idle_ticks->get_rtime(uc->xtal), + uc->idle_ticks->ticks, + (uc->ticks->ticks == 0)?0.0: + (100.0*((double)(uc->idle_ticks->ticks)/ + (double)(uc->ticks->ticks)))); + con->dd_printf("Max value of stack pointer= 0x%06x, avg= 0x%06x\n", + AU(uc->sp_max), AU(uc->sp_avg)); + con->dd_printf("Simulation: %s\n", + (uc->sim->state & SIM_GO)?"running":"stopped"); + return(0); +} + +CMDHELP(cl_state_cmd, + "state", + "State of microcontroller", + "long help of state") + +/* + * Command: file + *---------------------------------------------------------------------------- + */ + +//int +//cl_file_cmd::do_work(class cl_sim *sim, +// class cl_cmdline *cmdline, class cl_console *con) +COMMAND_DO_WORK_UC(cl_file_cmd) +{ + const char *fname= 0; + long l; + + if ((cmdline->param(0) == 0) || + ((fname= cmdline->param(0)->get_svalue()) == NULL)) + { + con->dd_printf("File name is missing.\n"); + return(0); + } + + if ((l= uc->read_file(fname, con)) >= 0) + ;//con->dd_printf("%ld words read from %s\n", l, fname); + + return(0); +} + +CMDHELP(cl_file_cmd, + "file \"FILE\"", + "Load FILE into ROM", + "long help of file") + +/* + * Command: download + *---------------------------------------------------------------------------- + */ + +//int +//cl_dl_cmd::do_work(class cl_sim *sim, +// class cl_cmdline *cmdline, class cl_console *con) +COMMAND_DO_WORK_UC(cl_dl_cmd) +{ + long l; + + if ((l= uc->read_hex_file(con)) >= 0) + con->dd_printf("%ld words loaded\n", l); + + return(0); +} + +CMDHELP(cl_dl_cmd, + "download", + "Load (intel.hex) data", + "long help of download") + +/* + * Command: pc + *---------------------------------------------------------------------------- + */ + +//int +//cl_pc_cmd::do_work(class cl_sim *sim, +// class cl_cmdline *cmdline, class cl_console *con) +COMMAND_DO_WORK_UC(cl_pc_cmd) +{ + t_addr addr; + class cl_cmd_arg *params[1]= { cmdline->param(0) }; + + if (params[0]) + { + if (!(params[0]->get_address(uc, &addr))) + { + con->dd_printf("Error: wrong parameter\n"); + return(false); + } + class cl_address_space *rom= uc->rom; + if (rom) + { + if (addr > rom->highest_valid_address()) + addr= rom->highest_valid_address(); + } + if (!uc->inst_at(addr)) + con->dd_printf("Warning: maybe not instruction at 0x%06x\n", AU(addr)); + uc->PC= addr; + } + uc->print_disass(uc->PC, con); + return(false); +} + +CMDHELP(cl_pc_cmd, + "pc [addr]", + "Set/get PC", + "long help of pc") + +/* + * Command: reset + *---------------------------------------------------------------------------- + */ + +//int +//cl_reset_cmd::do_work(class cl_sim *sim, +// class cl_cmdline *cmdline, class cl_console *con) +COMMAND_DO_WORK_UC(cl_reset_cmd) +{ + uc->reset(); + return(0); +} + +CMDHELP(cl_reset_cmd, + "reset", + "Reset processor to start state", + "long help of reset") + +/* + * Command: dump + *---------------------------------------------------------------------------- + */ + +//int +//cl_dump_cmd::do_work(class cl_sim *sim, +// class cl_cmdline *cmdline, class cl_console *con) +COMMAND_DO_WORK_UC(cl_dump_cmd) +{ + class cl_memory *mem= 0; + long bpl= 8; + t_addr start= 0, end; + class cl_cmd_arg *params[4]= { cmdline->param(0), + cmdline->param(1), + cmdline->param(2), + cmdline->param(3) }; + /*enum dump_format*/int fmt= df_hex; + + if (params[0] && + params[0]->as_bit(uc)) + { + int i= 0; + while (params[0] && + params[0]->as_bit(uc)) + { + t_mem m; + mem= params[0]->value.bit.mem; + m= mem->read(params[0]->value.bit.mem_address); + char *sn= + uc->symbolic_bit_name((t_addr)-1, + mem, + params[0]->value.bit.mem_address, + params[0]->value.bit.mask); + con->dd_printf("%10s ", sn?sn:""); + con->dd_printf(mem->addr_format, params[0]->value.bit.mem_address); + con->dd_printf(" "); + con->dd_printf(mem->data_format, m); + con->dd_printf(" %c\n", (m&(params[0]->value.bit.mask))?'1':'0'); + i++; + params[0]= cmdline->param(i); + } + if (params[0]) + syntax_error(con); + return false; + } + if (params[0] && + params[0]->as_string()) + { + char *s= params[0]->get_svalue(); + if (s && *s && + (strlen(s) > 1) && + (s[0]=='/')) + { + size_t i; + for (i= 0; i < strlen(s); i++) + s[i]= tolower(s[i]); + switch (tolower(s[1])) + { + case 's': fmt= df_string; break; + case 'h': fmt= df_hex; break; + case 'i': fmt= df_ihex; bpl= 32; break; + case 'b': + if (con->get_fout() && + con->get_fout()->tty) + return con->dd_printf("Error: binary format not supported on tty\n"), + false; + fmt= df_binary; + break; + } + if (strlen(s) > 2) + for (i= 2; i < strlen(s); i++) + { + switch (s[i]) + { + case 'l': fmt|= df_little; break; + case 'b': fmt|= df_big; break; + case '1': fmt|= df_1; break; + case '2': fmt|= df_2; break; + case '4': fmt|= df_4; break; + case '8': fmt|= df_8; break; + } + } + cmdline->shift(); + params[0]= cmdline->param(0); + params[1]= cmdline->param(1); + params[2]= cmdline->param(2); + params[3]= cmdline->param(3); + } + } + + enum dump_format df= (enum dump_format)fmt; + if ((cmdline->param(0)==NULL) || + (!(cmdline->param(0)->as_memory(uc)))) + { + con->dd_printf("No memory specified. Use \"info memory\" for available memories\n"); + return(false); + } + if (cmdline->syntax_match(uc, MEMORY)) + { + mem= cmdline->param(0)->value.memory.memory; + mem->dump(df, -1, -1, bpl, con/*->get_fout()*/); + } + else if (cmdline->syntax_match(uc, MEMORY ADDRESS)) { + mem = cmdline->param(0)->value.memory.memory; + start= cmdline->param(1)->value.address; + end = start+10*8-1; + mem->dump(df, start, end, bpl, con/*->get_fout()*/); + } + else if (cmdline->syntax_match(uc, MEMORY ADDRESS ADDRESS)) { + mem = cmdline->param(0)->value.memory.memory; + start= cmdline->param(1)->value.address; + end = cmdline->param(2)->value.address; + mem->dump(df, start, end, bpl, con/*->get_fout()*/); + } + else if (cmdline->syntax_match(uc, MEMORY ADDRESS ADDRESS NUMBER)) { + mem = cmdline->param(0)->value.memory.memory; + start= cmdline->param(1)->value.address; + end = cmdline->param(2)->value.address; + bpl = cmdline->param(3)->value.number; + mem->dump(df, start, end, bpl, con/*->get_fout()*/); + } + else + syntax_error(con); + + return(false);; +} + +CMDHELP(cl_dump_cmd, + "dump [/format] memory_type [start [stop [bytes_per_line]]] | dump bit...", + "Dump memory of specified type or bit(s)", + "long help of dump") + +/* + * Command: di + *---------------------------------------------------------------------------- + */ + +//int +//cl_di_cmd::do_work(class cl_sim *sim, +// class cl_cmdline *cmdline, class cl_console *con) +COMMAND_DO_WORK_UC(cl_di_cmd) +{ + cmdline->insert_param(0, new cl_cmd_sym_arg("iram")); + cl_dump_cmd::do_work(uc, cmdline, con); + return(0); +} + +CMDHELP(cl_di_cmd, + "di [start [stop]]", + "Dump Internal RAM", + "long help of di") + +/* + * Command: dx + *---------------------------------------------------------------------------- + */ + +//int +//cl_dx_cmd::do_work(class cl_sim *sim, +// class cl_cmdline *cmdline, class cl_console *con) +COMMAND_DO_WORK_UC(cl_dx_cmd) +{ + cmdline->insert_param(0, new cl_cmd_sym_arg("xram")); + cl_dump_cmd::do_work(uc, cmdline, con); + return(0); +} + +CMDHELP(cl_dx_cmd, + "dx [start [stop]]", + "Dump External RAM", + "long help of dx") + +/* + * Command: dch + *---------------------------------------------------------------------------- + */ + +//int +//cl_dch_cmd::do_work(class cl_sim *sim, +// class cl_cmdline *cmdline, class cl_console *con) +COMMAND_DO_WORK_UC(cl_dch_cmd) +{ + cmdline->insert_param(0, new cl_cmd_sym_arg(/*"rom"*/uc->rom->get_name("rom"))); + cl_dump_cmd::do_work(uc, cmdline, con); + return(0); +} + +CMDHELP(cl_dch_cmd, + "dch [start [stop]]", + "Dump code in hex form", + "long help of dch") + +/* + * Command: ds + *---------------------------------------------------------------------------- + */ + +//int +//cl_ds_cmd::do_work(class cl_sim *sim, +// class cl_cmdline *cmdline, class cl_console *con) +COMMAND_DO_WORK_UC(cl_ds_cmd) +{ + cmdline->insert_param(0, new cl_cmd_sym_arg("sfr")); + cl_dump_cmd::do_work(uc, cmdline, con); + return(0); +} + +CMDHELP(cl_ds_cmd, + "ds [start [stop]]", + "Dump SFR", + "long help of ds") + +/* + * Command: dc + *---------------------------------------------------------------------------- + */ + +//int +//cl_dc_cmd::do_work(class cl_sim *sim, +// class cl_cmdline *cmdline, class cl_console *con) +COMMAND_DO_WORK_UC(cl_dc_cmd) +{ + t_addr start= last, end= last+20; + class cl_cmd_arg *params[2]= { cmdline->param(0), + cmdline->param(1) }; + class cl_address_space *rom= uc->rom; + + if (!rom) + return(false); + if (params[0] == 0) + ; + else if (cmdline->syntax_match(uc, ADDRESS)) { + start= params[0]->value.address; + end= start+20; + } + else if (cmdline->syntax_match(uc, ADDRESS ADDRESS)) { + start= params[0]->value.address; + end= params[1]->value.address; + } + if (start > rom->highest_valid_address()) + { + con->dd_printf("Error: start address is too high\n"); + return(false); + } + if (end > rom->highest_valid_address()) + { + con->dd_printf("Error: end address is too high\n"); + return(false); + } + + for (; + start <= end; + start+= uc->inst_length(start)) + uc->print_disass(start, con); + last= start; + return(false); +} + +CMDHELP(cl_dc_cmd, + "dc [start [stop]]", + "Dump code in disass form", + "long help of dc") + +/* + * Command: disassemble + *---------------------------------------------------------------------------- + */ + +static int disass_last_stop= 0; + +//int +//cl_disassemble_cmd::do_work(class cl_sim *sim, +// class cl_cmdline *cmdline, class cl_console *con) +COMMAND_DO_WORK_UC(cl_disassemble_cmd) +{ + t_addr start, realstart; + int offset= -1, dir, lines= 20; + class cl_cmd_arg *params[4]= { cmdline->param(0), + cmdline->param(1), + cmdline->param(2), + cmdline->param(3) }; + + start= disass_last_stop; + if (params[0] == 0) ; + else if (cmdline->syntax_match(uc, ADDRESS)) { + start= params[0]->value.address; + } + else if (cmdline->syntax_match(uc, ADDRESS NUMBER)) { + start= params[0]->value.address; + offset= params[1]->value.number; + } + else if (cmdline->syntax_match(uc, ADDRESS NUMBER NUMBER)) { + start= params[0]->value.address; + offset= params[1]->value.number; + lines= params[2]->value.number; + } + else + { + syntax_error(con); + return(false); + } + + if (lines < 1) + { + con->dd_printf("Error: wrong `lines' parameter\n"); + return(false); + } + if (!uc->there_is_inst()) + return(false); + realstart= start; + class cl_address_space *rom= uc->rom; + if (!rom) + return(false); + while (realstart <= rom->highest_valid_address() && + !uc->inst_at(realstart)) + realstart= realstart+1; + if (offset) + { + dir= (offset < 0)?-1:+1; + while (offset) + { + realstart= rom->inc_address(realstart, dir); + while (!uc->inst_at(realstart)) + realstart= rom->inc_address(realstart, dir); + offset+= -dir; + } + } + + + while (lines) + { + int len; + uc->print_disass(realstart, con); + /* fix for #2383: start search next instruction after the actual one */ + len= uc->inst_length(realstart); + realstart= rom->inc_address(realstart, /*+1*/len) + rom->start_address; + while (!uc->inst_at(realstart)) + realstart= rom->inc_address(realstart, +1) + rom->start_address; + lines--; + } + + disass_last_stop= realstart; + + return(false);; +} + +CMDHELP(cl_disassemble_cmd, + "disassemble [start [offset [lines]]]", + "Disassemble code", + "long help of disassemble") + +/* + * Command: fill + *---------------------------------------------------------------------------- + */ + +//int +//cl_fill_cmd::do_work(class cl_sim *sim, +// class cl_cmdline *cmdline, class cl_console *con) +COMMAND_DO_WORK_UC(cl_fill_cmd) +{ + class cl_memory *mem= 0; + t_mem what= 0; + t_addr start= 0, end; + class cl_cmd_arg *params[4]= { cmdline->param(0), + cmdline->param(1), + cmdline->param(2), + cmdline->param(3) }; + + if (cmdline->syntax_match(uc, MEMORY ADDRESS ADDRESS NUMBER)) { + mem = params[0]->value.memory.memory; + start= params[1]->value.address; + end = params[2]->value.address; + what = params[3]->value.number; + t_addr i; + for (i= start; i <= end; i++) + { + t_mem d; + d= what; + mem->write(i, d); + } + } + else + syntax_error(con); + + return(false);; +} + +CMDHELP(cl_fill_cmd, + "fill memory_type start end data", + "Fill memory region with data", + "long help of fill") + +/* + * Command: where + *---------------------------------------------------------------------------- + */ + +int +cl_where_cmd::do_real_work(class cl_uc *uc, + class cl_cmdline *cmdline, class cl_console_base *con, + bool case_sensitive) +{ + class cl_memory *mem= 0; + class cl_cmd_arg *params[2]= { cmdline->param(0), + cmdline->param(1) }; + + if (cmdline->syntax_match(uc, MEMORY DATALIST)) { + mem= params[0]->value.memory.memory; + t_mem *array= params[1]->value.data_list.array; + int len= params[1]->value.data_list.len; + if (!len) + { + con->dd_printf("Error: nothing to search for\n"); + return(false); + } + t_addr addr= 0; + bool found= mem->search_next(case_sensitive, array, len, &addr); + while (found) + { + if (con->get_fout()) + mem->dump(addr, addr+len-1, 8, con/*->get_fout()*/); + addr++; + found= mem->search_next(case_sensitive, array, len, &addr); + } + } + else + syntax_error(con); + + return(false); +} + +//int +//cl_where_cmd::do_work(class cl_sim *sim, +// class cl_cmdline *cmdline, class cl_console *con) +COMMAND_DO_WORK_UC(cl_where_cmd) +{ + return(do_real_work(uc, cmdline, con, false)); +} + +CMDHELP(cl_where_cmd, + "where memory_type data...", + "Case unsensitive search for data", + "long help of where") + +//int +//cl_Where_cmd::do_work(class cl_sim *sim, +// class cl_cmdline *cmdline, class cl_console *con) +COMMAND_DO_WORK_UC(cl_Where_cmd) +{ + return(do_real_work(uc, cmdline, con, true)); +} + +CMDHELP(cl_Where_cmd, + "Where memory_type data...", + "Case sensitive search for data", + "long help of Where") + + +/* + * Command: hole + *---------------------------------------------------------------------------- + */ + +COMMAND_DO_WORK_UC(cl_hole_cmd) +{ + class cl_cmd_arg *params[4]= { cmdline->param(0), + cmdline->param(1), + cmdline->param(2) }; + class cl_memory *m= uc->rom; + + if (m) + { + t_mem v, a; + if (cmdline->syntax_match(uc, MEMORY NUMBER NUMBER)) + { + m= params[0]->value.memory.memory; + a= params[1]->value.number; + v= params[2]->value.number; + } + else if (cmdline->syntax_match(uc, MEMORY NUMBER)) + { + m= params[0]->value.memory.memory; + a= params[1]->value.number; + v= 0; + } + else if (cmdline->syntax_match(uc, MEMORY)) + { + m= params[0]->value.memory.memory; + a= 100; + v= 0; + } + else if (cmdline->syntax_match(uc, NUMBER NUMBER)) + { + a= params[0]->value.number; + v= params[1]->value.number; + } + else if (cmdline->syntax_match(uc, NUMBER)) + { + a= params[0]->value.number; + v= 0; + } + else + { + a= 100; + v= 0; + } + t_addr ad, l, h, sa= 0, len= 0; + t_mem mv; + bool in= false; + l= m->lowest_valid_address(); + h= m->highest_valid_address(); + //con->dd_printf("%s[0x%x-0x%0x] len=%d val=%d\n", m->get_name("mem"), + // l, h, a, v); + for (ad= l; ad <= h; ad++) + { + mv= m->read(ad); + if (!in && (mv==v)) + { + // found start + sa= ad; + in= true; + len= 0; + } + else if (in && (mv==v)) + { + // still inside + len++; + } + else if (in && (mv!=v)) + { + // found end + if (len >= a) + { + con->dd_printf(m->addr_format, sa); + con->dd_printf(" %u\n", AU(len)); + } + in= false; + } + } + if (in && + len >= a) + { + // found end after highest reached + con->dd_printf(m->addr_format, sa); + con->dd_printf(" %u\n", AU(len)); + } + } + return false; +} + +CMDHELP(cl_hole_cmd, + "hole [memory [length [value]]]", + "search area in memory (min length), filled with value", + "long help of hole") + + +/* + * Command: var + *---------------------------------------------------------------------------- + */ + +COMMAND_DO_WORK_UC(cl_var_cmd) +{ + class cl_cmd_arg *params[4]= { cmdline->param(0), + cmdline->param(1), + cmdline->param(2), + cmdline->param(3) }; + class cl_memory *m= NULL; + t_addr addr= -1; + int bit= -1; + class cl_var *v; + + if (cmdline->syntax_match(uc, STRING MEMORY ADDRESS NUMBER)) + { + m= params[1]->value.memory.memory; + addr= params[2]->value.address; + bit= params[3]->value.number; + } + else if (cmdline->syntax_match(uc, STRING MEMORY ADDRESS)) + { + m= params[1]->value.memory.memory; + addr= params[2]->value.address; + } + else if (cmdline->syntax_match(uc, STRING CELL)) + { + m= uc->address_space(params[1]->value.cell, &addr); + } + else if (cmdline->syntax_match(uc, STRING)) + { + } + else + return syntax_error(con), false; + + if (!valid_sym_name(params[0]->value.string.string)) + return con->dd_printf("name is invalid\n"), + false; + if ((bit >= 0) && + (bit >= (int)sizeof(t_mem)*8)) + return con->dd_printf("max bit number is %d\n", (int)sizeof(t_mem)*8), + false; + + if (m) + if (!m->is_address_space()) + return con->dd_printf("%s is not address space\n", m->get_name()), + false; + if (addr > 0) + if (!m->valid_address(addr)) + return con->dd_printf("invalid address\n"), + false; + if (bit >= 0) + if (bit >= 32) + return con->dd_printf("invalid bit number\n"), + false; + + if (uc->symbol2address(params[0]->value.string.string, + (class cl_address_space **)NULL, + (t_addr*)NULL)) + return con->dd_printf("already exists\n"), + false; + + if (m) + { + v= new cl_var(params[0]->value.string.string, + (cl_address_space*)m, addr, chars(""), bit); + v->init(); + uc->vars->add(v); + } + else + { + if (bit < 0) + { + if (addr < 0) + { + if (!uc->variables->search_cell(CELL_VAR, false, &addr)) + return con->dd_printf("no space\n"), + false; + } + if (!uc->variables->valid_address(addr)) + return con->dd_printf("out of range\n"), + false; + v= new cl_var(params[0]->value.string.string, + uc->variables, addr, chars(""), bit); + v->init(); + uc->vars->add(v); + } + else + { + } + } + + return false; +} + +CMDHELP(cl_var_cmd, + "var name [memory addr [bit_nr]]", + "Create new variable", + "long help of var") + +/* End of cmd.src/cmd_uc.cc */ |
