ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon_cmd.cpp
Revision: 1.15
Committed: 2003-09-27T20:33:06Z (21 years, 2 months ago) by cebix
Branch: MAIN
Changes since 1.14: +1 -1 lines
Log Message:
2002 -> 2003

File Contents

# User Rev Content
1 cebix 1.1 /*
2 cebix 1.9 * mon_cmd.cpp - cxmon standard commands
3 cebix 1.1 *
4 cebix 1.15 * cxmon (C) 1997-2003 Christian Bauer, Marc Hellwig
5 cebix 1.2 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 cebix 1.1 */
20    
21 cebix 1.2 #include "sysdeps.h"
22 cebix 1.1
23 cebix 1.4 #include <stdlib.h>
24    
25 cebix 1.1 #include "mon.h"
26     #include "mon_cmd.h"
27 cebix 1.7 #include "mon_disass.h"
28 cebix 1.1
29 hellwig 1.6 #ifndef VERSION
30 cebix 1.12 #define VERSION "3"
31 hellwig 1.6 #endif
32    
33 cebix 1.1
34     /*
35     * range_args = [expression] [[COMMA] expression] END
36     *
37     * Read start address to "adr", end address to "end_adr".
38     * "adr" defaults to '.', "end_adr" defaults to '.'+def_range
39     *
40     * true: OK, false: Error
41     */
42    
43 gbeauche 1.11 static bool range_args(uintptr *adr, uintptr *end_adr, uint32 def_range)
44 cebix 1.1 {
45     *adr = mon_dot_address;
46     *end_adr = mon_dot_address + def_range;
47    
48     if (mon_token == T_END)
49     return true;
50     else {
51     if (!mon_expression(adr))
52     return false;
53     *end_adr = *adr + def_range;
54     if (mon_token == T_END)
55     return true;
56     else {
57     if (mon_token == T_COMMA) mon_get_token();
58     if (!mon_expression(end_adr))
59     return false;
60     return mon_token == T_END;
61     }
62     }
63     }
64    
65    
66     /*
67     * byte_string = (expression | STRING) {COMMA (expression | STRING)} END
68     */
69    
70 gbeauche 1.11 static bool byte_string(uint8 *s, uintptr &len)
71 cebix 1.1 {
72 gbeauche 1.11 uintptr value;
73 cebix 1.1
74     len = 0;
75     goto start;
76    
77     for (;;) {
78     if (mon_token == T_COMMA) {
79     mon_get_token();
80    
81     start:
82     if (mon_token == T_STRING) {
83     uint8 *p = (uint8 *)mon_string;
84     while ((*s++ = *p++) != 0) ;
85     s--;
86     len += strlen(mon_string);
87     mon_get_token();
88     } else if (mon_expression(&value)) {
89     *s++ = value;
90     len++;
91     } else
92     return false;
93    
94     } else if (mon_token == T_END)
95     return true;
96     else {
97     mon_error("',' expected");
98     return false;
99     }
100     }
101     }
102    
103    
104     /*
105     * Convert character to printable character
106     */
107    
108     static inline uint8 char2print(uint8 c)
109     {
110     return (c >= 0x20 && c <= 0x7e) ? c : '.';
111     }
112    
113    
114     /*
115     * Show version
116     * ver
117     */
118    
119     void version(void)
120     {
121 cebix 1.5 fprintf(monout, "mon V" VERSION "\n");
122 cebix 1.1 }
123    
124    
125     /*
126     * Redirect output
127     * o [file]
128     */
129    
130     void redir_output(void)
131     {
132     // Close old file
133     if (monout != monerr) {
134     fclose(monout);
135     monout = monerr;
136     return;
137     }
138    
139     // No argument given?
140     if (mon_token == T_END)
141     return;
142    
143     // Otherwise open file
144     if (mon_token == T_STRING) {
145     mon_get_token();
146     if (mon_token != T_END) {
147     mon_error("Too many arguments");
148     return;
149     }
150     if (!(monout = fopen(mon_string, "w")))
151     mon_error("Unable to open file");
152     } else
153     mon_error("'\"' around file name expected");
154     }
155    
156    
157     /*
158     * Compute and display expression
159     * ? expression
160     */
161    
162     void print_expr(void)
163     {
164 gbeauche 1.11 uintptr val;
165 cebix 1.1
166     if (!mon_expression(&val))
167     return;
168     if (mon_token != T_END) {
169     mon_error("Too many arguments");
170     return;
171     }
172    
173     if (val > 0x7fffffff) {
174 cebix 1.3 fprintf(monout, "Hex unsigned: $%08x\n"
175     "Hex signed : -$%08x\n"
176     "Dec unsigned: %u\n"
177     "Dec signed : %d\n", val, -val, val, val);
178 cebix 1.1 fprintf(monout, "Char : '%c%c%c%c'\n", char2print(val >> 24), char2print(val >> 16), char2print(val >> 8), char2print(val));
179     } else {
180 cebix 1.3 fprintf(monout, "Hex : $%08x\n"
181     "Dec : %d\n", val, val);
182 cebix 1.1 fprintf(monout, "Char: '%c%c%c%c'\n", char2print(val >> 24), char2print(val >> 16), char2print(val >> 8), char2print(val));
183     }
184     }
185    
186    
187     /*
188     * Execute shell command
189     * \ "command"
190     */
191    
192     void shell_command(void)
193     {
194     if (mon_token != T_STRING) {
195     mon_error("'\"' around command expected");
196     return;
197     }
198     mon_get_token();
199     if (mon_token != T_END) {
200     mon_error("Too many arguments");
201     return;
202     }
203     system(mon_string);
204     }
205    
206    
207     /*
208     * Memory dump
209     * m [start [end]]
210     */
211    
212     #define MEMDUMP_BPL 16 // Bytes per line
213    
214     void memory_dump(void)
215     {
216 gbeauche 1.11 uintptr adr, end_adr;
217 cebix 1.1 uint8 mem[MEMDUMP_BPL + 1];
218    
219     mem[MEMDUMP_BPL] = 0;
220    
221     if (!range_args(&adr, &end_adr, 16 * MEMDUMP_BPL - 1)) // 16 lines unless end address specified
222     return;
223    
224     while (adr <= end_adr && !mon_aborted()) {
225 gbeauche 1.11 fprintf(monout, "%0*lx:", 2 * sizeof(adr), mon_use_real_mem ? adr: adr % mon_mem_size);
226 cebix 1.1 for (int i=0; i<MEMDUMP_BPL; i++, adr++) {
227     if (i % 4 == 0)
228 cebix 1.3 fprintf(monout, " %08x", mon_read_word(adr));
229 cebix 1.1 mem[i] = char2print(mon_read_byte(adr));
230     }
231     fprintf(monout, " '%s'\n", mem);
232     }
233    
234     mon_dot_address = adr;
235     }
236    
237    
238     /*
239     * ASCII dump
240     * i [start [end]]
241     */
242    
243     #define ASCIIDUMP_BPL 64 // Bytes per line
244    
245     void ascii_dump(void)
246     {
247 gbeauche 1.11 uintptr adr, end_adr;
248 cebix 1.1 uint8 str[ASCIIDUMP_BPL + 1];
249    
250     str[ASCIIDUMP_BPL] = 0;
251    
252     if (!range_args(&adr, &end_adr, 16 * ASCIIDUMP_BPL - 1)) // 16 lines unless end address specified
253     return;
254    
255     while (adr <= end_adr && !mon_aborted()) {
256 gbeauche 1.13 fprintf(monout, "%0*lx:", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
257 cebix 1.1 for (int i=0; i<ASCIIDUMP_BPL; i++, adr++)
258     str[i] = char2print(mon_read_byte(adr));
259     fprintf(monout, " '%s'\n", str);
260 cebix 1.5 }
261    
262     mon_dot_address = adr;
263     }
264    
265    
266     /*
267     * Binary dump
268     * b [start [end]]
269     */
270    
271     void binary_dump(void)
272     {
273 gbeauche 1.11 uintptr adr, end_adr;
274 cebix 1.5 uint8 str[9];
275    
276     str[8] = 0;
277    
278     if (!range_args(&adr, &end_adr, 7)) // 8 lines unless end address specified
279     return;
280    
281     while (adr <= end_adr && !mon_aborted()) {
282 gbeauche 1.13 fprintf(monout, "%0*lx:", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
283 cebix 1.5 uint8 b = mon_read_byte(adr);
284     for (int m=0x80, i=0; i<8; m>>=1, i++)
285     str[i] = (b & m) ? '*' : '.';
286     fprintf(monout, " '%s'\n", str);
287     adr++;
288 cebix 1.1 }
289    
290     mon_dot_address = adr;
291     }
292    
293    
294     /*
295     * Disassemble
296     * d [start [end]]
297     * d65 [start [end]]
298     * d68 [start [end]]
299     * d80 [start [end]]
300     * d86 [start [end]]
301 cebix 1.9 * d8086 [start [end]]
302 cebix 1.1 */
303    
304     enum CPUType {
305     CPU_PPC,
306     CPU_6502,
307     CPU_680x0,
308 cebix 1.9 CPU_Z80,
309 cebix 1.8 CPU_80x86_32,
310 gbeauche 1.13 CPU_80x86_16,
311     CPU_x86_64
312 cebix 1.1 };
313    
314     static void disassemble(CPUType type)
315     {
316 gbeauche 1.11 uintptr adr, end_adr;
317 cebix 1.1
318     if (!range_args(&adr, &end_adr, 16 * 4 - 1)) // 16 lines unless end address specified
319     return;
320    
321     switch (type) {
322     case CPU_PPC:
323     while (adr <= end_adr && !mon_aborted()) {
324     uint32 w = mon_read_word(adr);
325 gbeauche 1.13 fprintf(monout, "%0*lx: %08x\t", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size, w);
326 cebix 1.1 disass_ppc(monout, mon_use_real_mem ? adr : adr % mon_mem_size, w);
327     adr += 4;
328     }
329     break;
330    
331     case CPU_6502:
332     while (adr <= end_adr && !mon_aborted()) {
333     uint8 op = mon_read_byte(adr);
334     uint8 lo = mon_read_byte(adr + 1);
335     uint8 hi = mon_read_byte(adr + 2);
336 gbeauche 1.13 fprintf(monout, "%0*lx: ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
337 cebix 1.1 adr += disass_6502(monout, mon_use_real_mem ? adr : adr % mon_mem_size, op, lo, hi);
338     }
339     break;
340    
341     case CPU_680x0:
342     while (adr <= end_adr && !mon_aborted()) {
343 gbeauche 1.13 fprintf(monout, "%0*lx: ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
344 cebix 1.7 adr += disass_68k(monout, mon_use_real_mem ? adr : adr % mon_mem_size);
345 cebix 1.1 }
346     break;
347    
348 cebix 1.9 case CPU_Z80:
349 cebix 1.1 while (adr <= end_adr && !mon_aborted()) {
350 gbeauche 1.13 fprintf(monout, "%0*lx: ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
351 cebix 1.9 adr += disass_z80(monout, mon_use_real_mem ? adr : adr % mon_mem_size);
352 cebix 1.1 }
353     break;
354    
355 gbeauche 1.13 case CPU_x86_64:
356     while (adr <= end_adr && !mon_aborted()) {
357     fprintf(monout, "%0*lx: ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
358     adr += disass_x86(monout, mon_use_real_mem ? adr : adr % mon_mem_size, 64);
359     }
360     break;
361    
362 cebix 1.8 case CPU_80x86_32:
363 cebix 1.1 while (adr <= end_adr && !mon_aborted()) {
364 gbeauche 1.13 fprintf(monout, "%0*lx: ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
365     adr += disass_x86(monout, mon_use_real_mem ? adr : adr % mon_mem_size, 32);
366 cebix 1.8 }
367     break;
368    
369     case CPU_80x86_16:
370     while (adr <= end_adr && !mon_aborted()) {
371 gbeauche 1.13 fprintf(monout, "%0*lx: ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
372     adr += disass_x86(monout, mon_use_real_mem ? adr : adr % mon_mem_size, 16);
373 cebix 1.1 }
374     }
375    
376     mon_dot_address = adr;
377     }
378    
379     void disassemble_ppc(void)
380     {
381     disassemble(CPU_PPC);
382     }
383    
384     void disassemble_6502(void)
385     {
386     disassemble(CPU_6502);
387     }
388    
389     void disassemble_680x0(void)
390     {
391     disassemble(CPU_680x0);
392     }
393    
394 cebix 1.9 void disassemble_z80(void)
395 cebix 1.1 {
396 cebix 1.9 disassemble(CPU_Z80);
397 cebix 1.1 }
398    
399 cebix 1.8 void disassemble_80x86_32(void)
400     {
401     disassemble(CPU_80x86_32);
402     }
403    
404     void disassemble_80x86_16(void)
405 cebix 1.1 {
406 cebix 1.8 disassemble(CPU_80x86_16);
407 cebix 1.1 }
408    
409 gbeauche 1.13 void disassemble_x86_64(void)
410     {
411     disassemble(CPU_x86_64);
412     }
413    
414 cebix 1.1
415     /*
416     * Modify memory
417     * : addr bytestring
418     */
419    
420     void modify(void)
421     {
422 gbeauche 1.11 uintptr adr, len, src_adr = 0;
423 cebix 1.1 uint8 str[256];
424    
425     if (!mon_expression(&adr))
426     return;
427     if (!byte_string(str, len))
428     return;
429    
430     while (src_adr < len)
431     mon_write_byte(adr++, str[src_adr++]);
432    
433     mon_dot_address = adr;
434     }
435    
436    
437     /*
438     * Fill
439     * f start end bytestring
440     */
441    
442     void fill(void)
443     {
444 gbeauche 1.11 uintptr adr, end_adr, len, src_adr = 0;
445 cebix 1.1 uint8 str[256];
446    
447     if (!mon_expression(&adr))
448     return;
449     if (!mon_expression(&end_adr))
450     return;
451     if (!byte_string(str, len))
452     return;
453    
454     while (adr <= end_adr)
455     mon_write_byte(adr++, str[src_adr++ % len]);
456     }
457    
458    
459     /*
460     * Transfer memory
461     * t start end dest
462     */
463    
464     void transfer(void)
465     {
466 gbeauche 1.11 uintptr adr, end_adr, dest;
467 cebix 1.1 int num;
468    
469     if (!mon_expression(&adr))
470     return;
471     if (!mon_expression(&end_adr))
472     return;
473     if (!mon_expression(&dest))
474     return;
475     if (mon_token != T_END) {
476     mon_error("Too many arguments");
477     return;
478     }
479    
480     num = end_adr - adr + 1;
481    
482     if (dest < adr)
483     for (int i=0; i<num; i++)
484     mon_write_byte(dest++, mon_read_byte(adr++));
485     else {
486     dest += end_adr - adr;
487     for (int i=0; i<num; i++)
488     mon_write_byte(dest--, mon_read_byte(end_adr--));
489     }
490     }
491    
492    
493     /*
494     * Compare
495     * c start end dest
496     */
497    
498     void compare(void)
499     {
500 gbeauche 1.11 uintptr adr, end_adr, dest;
501 cebix 1.1 int num = 0;
502    
503     if (!mon_expression(&adr))
504     return;
505     if (!mon_expression(&end_adr))
506     return;
507     if (!mon_expression(&dest))
508     return;
509     if (mon_token != T_END) {
510     mon_error("Too many arguments");
511     return;
512     }
513    
514     while (adr <= end_adr && !mon_aborted()) {
515     if (mon_read_byte(adr) != mon_read_byte(dest)) {
516 gbeauche 1.13 fprintf(monout, "%0*lx ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
517 cebix 1.1 num++;
518     if (!(num & 7))
519     fputc('\n', monout);
520     }
521     adr++; dest++;
522     }
523    
524     if (num & 7)
525     fputc('\n', monout);
526     fprintf(monout, "%d byte(s) different\n", num);
527     }
528    
529    
530     /*
531     * Search for byte string
532     * h start end bytestring
533     */
534    
535     void hunt(void)
536     {
537 gbeauche 1.11 uintptr adr, end_adr, len;
538 cebix 1.1 uint8 str[256];
539     int num = 0;
540    
541     if (!mon_expression(&adr))
542     return;
543     if (!mon_expression(&end_adr))
544     return;
545     if (!byte_string(str, len))
546     return;
547    
548     while ((adr+len-1) <= end_adr && !mon_aborted()) {
549     uint32 i;
550    
551     for (i=0; i<len; i++)
552     if (mon_read_byte(adr + i) != str[i])
553     break;
554    
555     if (i == len) {
556 gbeauche 1.13 fprintf(monout, "%0*lx ", 2 * sizeof(adr), mon_use_real_mem ? adr : adr % mon_mem_size);
557 cebix 1.1 num++;
558     if (num == 1)
559     mon_dot_address = adr;
560     if (!(num & 7))
561     fputc('\n', monout);
562     }
563     adr++;
564     }
565    
566     if (num & 7)
567     fputc('\n', monout);
568     fprintf(monout, "Found %d occurrences\n", num);
569     }
570    
571    
572     /*
573     * Load data
574     * [ start "file"
575     */
576    
577     void load_data(void)
578     {
579 gbeauche 1.11 uintptr start_adr;
580 cebix 1.1 FILE *file;
581     int fc;
582    
583     if (!mon_expression(&start_adr))
584     return;
585     if (mon_token == T_END) {
586     mon_error("Missing file name");
587     return;
588     }
589     if (mon_token != T_STRING) {
590     mon_error("'\"' around file name expected");
591     return;
592     }
593     mon_get_token();
594     if (mon_token != T_END) {
595     mon_error("Too many arguments");
596     return;
597     }
598    
599     if (!(file = fopen(mon_string, "rb")))
600     mon_error("Unable to open file");
601     else {
602 gbeauche 1.11 uintptr adr = start_adr;
603 cebix 1.1
604     while ((fc = fgetc(file)) != EOF)
605     mon_write_byte(adr++, fc);
606     fclose(file);
607    
608 gbeauche 1.13 fprintf(monerr, "%08x bytes read from %0*lx to %0*lx\n", adr - start_adr, 2 * sizeof(adr), mon_use_real_mem ? start_adr : start_adr % mon_mem_size, 2 * sizeof(adr), mon_use_real_mem ? adr-1 : (adr-1) % mon_mem_size);
609 cebix 1.1 mon_dot_address = adr;
610     }
611     }
612    
613    
614     /*
615     * Save data
616     * ] start size "file"
617     */
618    
619     void save_data(void)
620     {
621 gbeauche 1.11 uintptr start_adr, size;
622 cebix 1.1 FILE *file;
623    
624     if (!mon_expression(&start_adr))
625     return;
626     if (!mon_expression(&size))
627     return;
628     if (mon_token == T_END) {
629     mon_error("Missing file name");
630     return;
631     }
632     if (mon_token != T_STRING) {
633     mon_error("'\"' around file name expected");
634     return;
635     }
636     mon_get_token();
637     if (mon_token != T_END) {
638     mon_error("Too many arguments");
639     return;
640     }
641    
642     if (!(file = fopen(mon_string, "wb")))
643     mon_error("Unable to create file");
644     else {
645 gbeauche 1.11 uintptr adr = start_adr, end_adr = start_adr + size - 1;
646 cebix 1.1
647     while (adr <= end_adr)
648     fputc(mon_read_byte(adr++), file);
649     fclose(file);
650    
651 cebix 1.14 fprintf(monerr, "%08x bytes written from %0*lx to %0*lx\n", size, 2 * sizeof(adr), mon_use_real_mem ? start_adr : start_adr % mon_mem_size, 2 * sizeof(adr), mon_use_real_mem ? end_adr : end_adr % mon_mem_size);
652 cebix 1.1 }
653     }