11#include "cli.h"
22
33#include "3rd/disassembler.h"
4+ #include "breakpoint.h"
45#include "bus.h"
56#include "ceda_string.h"
67#include "cpu.h"
@@ -80,7 +81,7 @@ static ceda_string_t *cli_pause(const char *arg) {
8081
8182static ceda_string_t * cli_continue (const char * arg ) {
8283 (void )arg ;
83- cpu_step (); // possibly step past the breakpoint
84+ monitor_pass ();
8485 cpu_pause (false);
8586 return NULL ;
8687}
@@ -124,49 +125,107 @@ static ceda_string_t *cli_step(const char *arg) {
124125}
125126
126127static ceda_string_t * cli_break (const char * arg ) {
127- char word [LINE_BUFFER_SIZE ];
128128
129- // skip argv[0]
129+ char word [ LINE_BUFFER_SIZE ];
130130 arg = tokenizer_next_word (word , arg , LINE_BUFFER_SIZE );
131131
132- // extract address
132+ char what [LINE_BUFFER_SIZE ];
133+ arg = tokenizer_next_word (what , arg , LINE_BUFFER_SIZE );
134+ bool is_what = arg != NULL ;
135+
133136 unsigned int _address ;
137+ zuint16 address = 0 ;
134138 arg = tokenizer_next_hex (& _address , arg );
139+ bool is_address = arg != NULL ;
140+ if (is_address ) {
141+ if (_address >= 0x10000 ) {
142+ ceda_string_t * msg = ceda_string_new (0 );
143+ ceda_string_cpy (msg , USER_BAD_ARG_STR "address must be 16 bit\n" );
144+ return msg ;
145+ }
146+ address = (zuint16 )_address ;
147+ }
135148
136- // no address => show current breakpoints
137- if (arg == NULL ) {
138- CpuBreakpoint * breakpoints ;
139- const size_t countof_breakpoints = cpu_getBreakpoints (& breakpoints );
149+ unsigned int _value ;
150+ zuint8 value = 0 ;
151+ arg = tokenizer_next_hex (& _value , arg );
152+ bool is_value = arg != NULL ;
153+ if (is_value ) {
154+ if (_value >= 0x100 ) {
155+ ceda_string_t * msg = ceda_string_new (0 );
156+ ceda_string_cpy (msg , USER_BAD_ARG_STR "value must be 8 bit\n" );
157+ return msg ;
158+ }
159+ value = (zuint8 )_value ;
160+ }
161+
162+ // no "what" => show current monitors
163+ if (!is_what ) {
164+ const Monitor * monitors ;
165+ const size_t countof_breakpoints = monitor_get (& monitors );
140166 int count = 0 ;
141167 ceda_string_t * msg = ceda_string_new (0 );
142168 for (size_t i = 0 ; i < countof_breakpoints ; ++ i ) {
143- if (!breakpoints [i ].valid )
169+ if (!monitors [i ].valid )
144170 continue ;
171+ static const struct associator_t {
172+ monitor_kind_t kind ;
173+ char letter ;
174+ } associators [] = {
175+ {MONITOR_EXEC , 'X' }, //
176+ {MONITOR_READ_MEM , 'R' }, //
177+ {MONITOR_WRITE_MEM , 'W' }, //
178+ {MONITOR_READ_IO , 'i' }, //
179+ {MONITOR_WRITE_IO , 'o' }, //
180+ };
181+ char kind = '-' ;
182+ for (size_t j = 0 ; j < ARRAY_SIZE (associators ); ++ j ) {
183+ if (associators [j ].kind == monitors [i ].kind ) {
184+ kind = associators [j ].letter ;
185+ break ;
186+ }
187+ }
145188 ++ count ;
146- ceda_string_printf (msg , "%lu\t%04x\n" , i , breakpoints [i ].address );
189+ ceda_string_printf (msg , "%lu\t%c\t%04x\n" , i , kind ,
190+ monitors [i ].address );
147191 }
148192 if (count == 0 ) {
149193 ceda_string_cpy (msg , "no breakpoint set\n" );
150194 }
151195 return msg ;
152196 }
197+ // add a new monitor
153198
154- if (_address >= 0x10000 ) {
199+ if (! is_address ) {
155200 ceda_string_t * msg = ceda_string_new (0 );
156- ceda_string_cpy (msg , USER_BAD_ARG_STR "address must be 16 bit \n" );
201+ ceda_string_cpy (msg , USER_BAD_ARG_STR "missing address \n" );
157202 return msg ;
158203 }
159- const zuint16 address = (zuint16 )_address ;
160204
161- // actually set breakpoint
162- bool ret = cpu_addBreakpoint (address );
205+ bool ret = false;
206+ if (strcmp (what , "break" ) == 0 ) {
207+ ret = monitor_addBreakpoint (address );
208+ } else if (strcmp (what , "read" ) == 0 ) {
209+ ret = monitor_addReadWatchpoint (address );
210+ } else if (strcmp (what , "write" ) == 0 ) {
211+ ret = monitor_addWriteWatchpoint (address , is_value ? & value : NULL );
212+ } else if (strcmp (what , "in" ) == 0 ) {
213+ ret = monitor_addInWatchpoint (address );
214+ } else if (strcmp (what , "out" ) == 0 ) {
215+ ret = monitor_addOutWatchpoint (address , is_value ? & value : NULL );
216+ } else {
217+ ceda_string_t * msg = ceda_string_new (0 );
218+ ceda_string_cpy (msg , USER_BAD_ARG_STR "unknown monitor kind\n" );
219+ return msg ;
220+ }
163221
164222 if (!ret ) {
165223 ceda_string_t * msg = ceda_string_new (0 );
166224 ceda_string_cpy (msg , USER_NO_SPACE_LEFT_STR );
167225 return msg ;
168226 }
169227
228+ // all ok, no output
170229 return NULL ;
171230}
172231
@@ -178,16 +237,6 @@ static ceda_string_t *cli_delete(const char *arg) {
178237 // skip argv[0]
179238 arg = tokenizer_next_word (word , arg , LINE_BUFFER_SIZE );
180239
181- char what [LINE_BUFFER_SIZE ];
182- // extract what to delete (breakpoint, watchpoint, ...)
183- arg = tokenizer_next_word (what , arg , LINE_BUFFER_SIZE );
184-
185- // missing what
186- if (arg == NULL ) {
187- ceda_string_cpy (msg , USER_BAD_ARG_STR "missing delete target\n" );
188- return msg ;
189- }
190-
191240 // extract index
192241 arg = tokenizer_next_word (word , arg , LINE_BUFFER_SIZE );
193242
@@ -206,15 +255,8 @@ static ceda_string_t *cli_delete(const char *arg) {
206255 }
207256
208257 // actually delete something
209- if (strcmp (what , "breakpoint" ) == 0 ) {
210- if (!cpu_deleteBreakpoint (index )) {
211- ceda_string_cpy (msg , "can't delete breakpoint\n" );
212- return msg ;
213- }
214- } else if (strcmp (what , "watchpoint" ) == 0 ) {
215- // TODO(giomba): implement this for watchpoints
216- } else {
217- ceda_string_cpy (msg , USER_BAD_ARG_STR "unknown delete target\n" );
258+ if (!monitor_delete (index )) {
259+ ceda_string_cpy (msg , "can't delete monitor\n" );
218260 return msg ;
219261 }
220262
@@ -361,9 +403,9 @@ static ceda_string_t *cli_dis(const char *arg) {
361403 * Expected command line syntax:
362404 * save <filename> <start> <end>
363405 * where
364- * filename: name of the file where to save the dump (no spaces allowed)
365- * start: starting memory address, in hex
366- * end: ending memory address, in hex
406+ * filename: name of the file where to save the dump (no spaces
407+ * allowed) start: starting memory address, in hex end: ending memory
408+ * address, in hex
367409 *
368410 * Data is saved [start;end)
369411 *
@@ -376,7 +418,8 @@ static ceda_string_t *cli_dis(const char *arg) {
376418 *
377419 * @param arg Pointer to the command line string.
378420 *
379- * @return char* NULL in case of success, pointer to error message otherwise.
421+ * @return char* NULL in case of success, pointer to error message
422+ * otherwise.
380423 */
381424static ceda_string_t * cli_save (const char * arg ) {
382425 char word [LINE_BUFFER_SIZE ];
@@ -611,9 +654,10 @@ static ceda_string_t *cli_umount(const char *arg) {
611654 * filename: name of the file from which to load the dump (no spaces
612655 * allowed) start: starting memory address, in hex
613656 *
614- * When loading, this routine will use the starting address saves inside the
615- * file, unless a starting address is explicitly specified on the command
616- * line, in which case, the starting address of the file will be overridden.
657+ * When loading, this routine will use the starting address saves inside
658+ * the file, unless a starting address is explicitly specified on the
659+ * command line, in which case, the starting address of the file will be
660+ * overridden.
617661 *
618662 * Example: load video memory dump, but one row below
619663 * load video.crt d050
@@ -808,7 +852,7 @@ static ceda_string_t *cli_help(const char *arg);
808852static const cli_command cli_commands [] = {
809853 {"dis" , "disassembly binary data" , cli_dis },
810854 {"break" , "set or show cpu breakpoints" , cli_break },
811- {"delete" , "delete cpu breakpoint" , cli_delete },
855+ {"delete" , "delete cpu monitor/ breakpoint" , cli_delete },
812856 {"pause" , "pause cpu execution" , cli_pause },
813857 {"continue" , "continue cpu execution" , cli_continue },
814858 {"reg" , "show cpu registers" , cli_reg },
0 commit comments