/* ======================================================================= SAMPLE.C - A customized application-specific C25 simulator Copyright (C) 1995 Will Ware This program 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. This program 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 this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ======================================================================= */ #include "stdio.h" #include "stdlib.h" #include "conio.h" #include "string.h" #include "c25lib.h" #define next_link(p) ((char *) *((int *)(p))) #define set_next_link(p,n) *((char **) (p)) = n #define string_part(p) (((char *) (p)) + sizeof(char *)) char toprint[100], *first_symbol, name[40], fline[80], dummy2[40]; /* ======================================================================= */ /* Wait States */ /* ======================================================================= */ void __write(char *s) { printf("%s", s); } #define ui(x) ((unsigned int) (x)) #define range(x,lo,hi) ((ui(x) >= ui(lo)) && (ui(x) <= ui(hi))) int program_wait_states(unsigned int addr) { /* narrow range of very slow memory */ if (range(addr, 0x98, 0xA0)) return 10; /* everything else is zero-wait-state */ return 0; } /* ======================================================================= */ /* Symbol Table */ /* ======================================================================= */ char *add_line(char **head, char *line) { char *p, *q; q = (char *) malloc(sizeof(char *) + strlen(line) + 1); if (q == NULL) return q; strcpy(string_part(q), line); set_next_link(q, NULL); if (*head == NULL) { *head = q; return q; } for (p = *head; next_link(p) != NULL; p = next_link(p)); set_next_link(p, q); return q; } void load_map_file(char *word) { int i, addr, dummy1; FILE *f; for (i = 0; i < (int) strlen(word); i++) word[i] = toupper(word[i]); if (strchr(word, '.') == NULL) sprintf(name, "%s.map", word); else strcpy(name, word); f = fopen(name, "r"); if (f == NULL) { printf("No map file available\n"); return; } while (1) { fgets(fline, 80, f); if (strcmp(fline, "GLOBAL SYMBOLS\n") == 0) break; if (feof(f)) { fclose(f); return; } } fgets(fline, 80, f); fgets(fline, 80, f); fgets(fline, 80, f); first_symbol = NULL; while (1) { fgets(fline, 80, f); if (sscanf(fline, "%x %s %x %s", &addr, name, &dummy1, dummy2) < 4) goto fini; sprintf(fline, "%s %04X", name, addr); if (add_line(&first_symbol, fline) == NULL) { __write("Out of room for labels and global variables!\n"); goto fini; } } fini: fclose(f); return; } int lookup_symbol(char *name) { int n; char *p, q[40]; for (p = first_symbol; p != NULL; p = next_link(p)) { sscanf(string_part(p), "%s %x", q, &n); if (strcmpi(q, name) == 0) return n; } printf("Couldn't find symbol \"%s\"\n", name); return 0; } int print_matching_symbols(int a) { char *p, q[40]; int x, n = 0; for (p = first_symbol; p != NULL; p = next_link(p)) { sscanf(string_part(p), "%s %x", q, &x); if (x == a) { printf("%s\n", q); n++; } } return n; } int print_all_symbols(void) { char *p; int n = 0; for (p = first_symbol; p != NULL; p = next_link(p)) { printf("%s\n", string_part(p)); n++; } return n; } /* ======================================================================= */ /* Main */ /* ======================================================================= */ int cp, rstring; void note_change(int *current, int *previous, char *name) { if (*previous != *current) { /* print the new values */ printf("%ld cycles %s=%04X\n", cycles, name, *current); /* and update the previous value */ *previous = *current; } } char str[] = "Supercalifragilistic"; int strptr = 0; void getch2(void) { switch (toupper(getch())) { case 0: getch(); break; case 'Q': exit(0); break; default: break; } } void main(void) { int i, c, mode = 0, *k, *L, id, i1, i2, ri_counter, k_previous, L_previous, ar4_previous, ar5_previous; unsigned long int next_rint; /* First set up the simulator and load some files. */ initialize_simulator(); load_hex_files("foo"); /* C25 executable */ load_map_file("foo"); /* symbol table */ k = data_memory_address(lookup_symbol("_k")); L = data_memory_address(lookup_symbol("_L")); id = lookup_symbol("_idle_here"); i1 = lookup_symbol("tint"); i2 = lookup_symbol("rint"); cp = lookup_symbol("cptr"); rstring = lookup_symbol("rstring"); /* Set up wait states for slow program memory */ pwaitf = program_wait_states; next_rint = 600; while (1) { /* Execute one instruction */ advance(); /* Report only when something changes */ if (mode) { note_change(&ar[4], &ar4_previous, "ar4"); note_change(&ar[5], &ar5_previous, "ar5"); note_change(k, &k_previous, "k"); note_change(L, &L_previous, "L"); } /* Footnote interrupts */ if (pc == i1) printf("TINT Interrupt at cycle # %ld\n", cycles); if (pc == i2) printf("RINT Interrupt at cycle # %ld\n", cycles); if (pc == id) printf("Idle at cycle # %ld\n", cycles); if (cycles >= next_rint) { drr = (int) str[strptr]; strptr = (strptr + 1) % (strlen(str) + 1); c25_interrupt(RINT); next_rint += 1200; } if (kbhit()) switch (toupper(getch())) { /* Pressing Q will quit the program */ case 'Q': return; /* Pressing R will get a long report */ case 'R': long_report(); break; /* Pressing M will toggle k,L report mode */ case 'M': mode = !mode; break; /* Pressing S will print the received string */ case 'S': i = rstring; while ((c = read_data_memory(i++)) != 0) printf("%c", (char) c); printf("\n"); getch2(); break; /* Pressing any other key will get a short report */ default: short_report(); getch2(); break; } } }