ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/mon_cmd.cpp
Revision: 1.6
Committed: 2000-06-10T19:07:37Z (23 years, 11 months ago) by hellwig
Branch: MAIN
Changes since 1.5: +4 -0 lines
Log Message:
- changes for SheepShaver

File Contents

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