99#include "floppy.h"
1010#include "int.h"
1111#include "macro.h"
12+ #include "monitor.h"
1213#include "serial.h"
1314#include "time.h"
1415#include "tokenizer.h"
@@ -90,7 +91,6 @@ static ceda_string_t *cli_pause(const char *arg) {
9091
9192static ceda_string_t * cli_continue (const char * arg ) {
9293 (void )arg ;
93- cpu_step (); // possibly step past the breakpoint
9494 cpu_pause (false);
9595 return NULL ;
9696}
@@ -134,49 +134,92 @@ static ceda_string_t *cli_step(const char *arg) {
134134}
135135
136136static ceda_string_t * cli_break (const char * arg ) {
137- char word [LINE_BUFFER_SIZE ];
138137
139- // skip argv[0]
138+ char word [ LINE_BUFFER_SIZE ];
140139 arg = tokenizer_next_word (word , arg , LINE_BUFFER_SIZE );
141140
142- // extract address
141+ char what [LINE_BUFFER_SIZE ];
142+ arg = tokenizer_next_word (what , arg , LINE_BUFFER_SIZE );
143+ bool is_what = arg != NULL ;
144+
143145 unsigned int _address ;
146+ zuint16 address = 0 ;
144147 arg = tokenizer_next_hex (& _address , arg );
148+ bool is_address = arg != NULL ;
149+ if (is_address ) {
150+ if (_address >= 0x10000 ) {
151+ ceda_string_t * msg = ceda_string_new (0 );
152+ ceda_string_cpy (msg , USER_BAD_ARG_STR "address must be 16 bit\n" );
153+ return msg ;
154+ }
155+ address = (zuint16 )_address ;
156+ }
145157
146- // no address => show current breakpoints
147- if (arg == NULL ) {
148- CpuBreakpoint * breakpoints ;
149- const size_t countof_breakpoints = cpu_getBreakpoints (& breakpoints );
158+ unsigned int _value ;
159+ zuint8 value = 0 ;
160+ arg = tokenizer_next_hex (& _value , arg );
161+ bool is_value = arg != NULL ;
162+ if (is_value ) {
163+ if (_value >= 0x100 ) {
164+ ceda_string_t * msg = ceda_string_new (0 );
165+ ceda_string_cpy (msg , USER_BAD_ARG_STR "value must be 8 bit\n" );
166+ return msg ;
167+ }
168+ value = (zuint8 )_value ;
169+ }
170+
171+ // no "what" => show current monitors
172+ if (!is_what ) {
173+ const Monitor * monitors ;
174+ const size_t countof_breakpoints = monitor_get (& monitors );
150175 int count = 0 ;
151176 ceda_string_t * msg = ceda_string_new (0 );
152177 for (size_t i = 0 ; i < countof_breakpoints ; ++ i ) {
153- if (!breakpoints [i ].valid )
178+ if (!monitors [i ].valid )
154179 continue ;
180+ const char * description =
181+ monitor_getKindDescription (monitors [i ].kind );
155182 ++ count ;
156- ceda_string_printf (msg , "%lu\t%04x\n" , i , breakpoints [i ].address );
183+ ceda_string_printf (msg , "%lu\t%s\t%04x\n" , i , description ,
184+ monitors [i ].address );
157185 }
158186 if (count == 0 ) {
159187 ceda_string_cpy (msg , "no breakpoint set\n" );
160188 }
161189 return msg ;
162190 }
191+ // add a new monitor
163192
164- if (_address >= 0x10000 ) {
193+ if (! is_address ) {
165194 ceda_string_t * msg = ceda_string_new (0 );
166- ceda_string_cpy (msg , USER_BAD_ARG_STR "address must be 16 bit \n" );
195+ ceda_string_cpy (msg , USER_BAD_ARG_STR "missing address \n" );
167196 return msg ;
168197 }
169- const uint16_t address = (uint16_t )_address ;
170198
171- // actually set breakpoint
172- bool ret = cpu_addBreakpoint (address );
199+ bool ret = false;
200+ if (strcmp (what , "exec" ) == 0 ) {
201+ ret = monitor_addBreakpoint (address );
202+ } else if (strcmp (what , "read" ) == 0 ) {
203+ ret = monitor_addReadWatchpoint (address );
204+ } else if (strcmp (what , "write" ) == 0 ) {
205+ ret = monitor_addWriteWatchpoint (address , is_value ? & value : NULL );
206+ } else if (strcmp (what , "in" ) == 0 ) {
207+ ret = monitor_addInWatchpoint (address );
208+ } else if (strcmp (what , "out" ) == 0 ) {
209+ ret = monitor_addOutWatchpoint (address , is_value ? & value : NULL );
210+ } else {
211+ ceda_string_t * msg = ceda_string_new (0 );
212+ ceda_string_cpy (msg , USER_BAD_ARG_STR "unknown monitor kind\n" );
213+ return msg ;
214+ }
173215
174216 if (!ret ) {
175217 ceda_string_t * msg = ceda_string_new (0 );
176218 ceda_string_cpy (msg , USER_NO_SPACE_LEFT_STR );
177219 return msg ;
178220 }
179221
222+ // all ok, no output
180223 return NULL ;
181224}
182225
@@ -188,16 +231,6 @@ static ceda_string_t *cli_delete(const char *arg) {
188231 // skip argv[0]
189232 arg = tokenizer_next_word (word , arg , LINE_BUFFER_SIZE );
190233
191- char what [LINE_BUFFER_SIZE ];
192- // extract what to delete (breakpoint, watchpoint, ...)
193- arg = tokenizer_next_word (what , arg , LINE_BUFFER_SIZE );
194-
195- // missing what
196- if (arg == NULL ) {
197- ceda_string_cpy (msg , USER_BAD_ARG_STR "missing delete target\n" );
198- return msg ;
199- }
200-
201234 // extract index
202235 arg = tokenizer_next_word (word , arg , LINE_BUFFER_SIZE );
203236
@@ -216,15 +249,8 @@ static ceda_string_t *cli_delete(const char *arg) {
216249 }
217250
218251 // actually delete something
219- if (strcmp (what , "breakpoint" ) == 0 ) {
220- if (!cpu_deleteBreakpoint (index )) {
221- ceda_string_cpy (msg , "can't delete breakpoint\n" );
222- return msg ;
223- }
224- } else if (strcmp (what , "watchpoint" ) == 0 ) {
225- // TODO(giomba): implement this for watchpoints
226- } else {
227- ceda_string_cpy (msg , USER_BAD_ARG_STR "unknown delete target\n" );
252+ if (!monitor_delete (index )) {
253+ ceda_string_cpy (msg , "can't delete monitor\n" );
228254 return msg ;
229255 }
230256
@@ -371,9 +397,9 @@ static ceda_string_t *cli_dis(const char *arg) {
371397 * Expected command line syntax:
372398 * save <filename> <start> <end>
373399 * where
374- * filename: name of the file where to save the dump (no spaces allowed)
375- * start: starting memory address, in hex
376- * end: ending memory address, in hex
400+ * filename: name of the file where to save the dump (no spaces
401+ * allowed) start: starting memory address, in hex end: ending memory
402+ * address, in hex
377403 *
378404 * Data is saved [start;end)
379405 *
@@ -386,7 +412,8 @@ static ceda_string_t *cli_dis(const char *arg) {
386412 *
387413 * @param arg Pointer to the command line string.
388414 *
389- * @return char* NULL in case of success, pointer to error message otherwise.
415+ * @return char* NULL in case of success, pointer to error message
416+ * otherwise.
390417 */
391418static ceda_string_t * cli_save (const char * arg ) {
392419 char word [LINE_BUFFER_SIZE ];
@@ -621,9 +648,10 @@ static ceda_string_t *cli_umount(const char *arg) {
621648 * filename: name of the file from which to load the dump (no spaces
622649 * allowed) start: starting memory address, in hex
623650 *
624- * When loading, this routine will use the starting address saves inside the
625- * file, unless a starting address is explicitly specified on the command
626- * line, in which case, the starting address of the file will be overridden.
651+ * When loading, this routine will use the starting address saves inside
652+ * the file, unless a starting address is explicitly specified on the
653+ * command line, in which case, the starting address of the file will be
654+ * overridden.
627655 *
628656 * Example: load video memory dump, but one row below
629657 * load video.crt d050
@@ -824,7 +852,7 @@ static ceda_string_t *cli_help(const char *arg);
824852static const cli_command cli_commands [] = {
825853 {"dis" , "disassembly binary data" , cli_dis },
826854 {"break" , "set or show cpu breakpoints" , cli_break },
827- {"delete" , "delete cpu breakpoint" , cli_delete },
855+ {"delete" , "delete cpu monitor/ breakpoint" , cli_delete },
828856 {"pause" , "pause cpu execution" , cli_pause },
829857 {"continue" , "continue cpu execution" , cli_continue },
830858 {"reg" , "show cpu registers" , cli_reg },
0 commit comments