Article 2593 of comp.sys.handhelds: Path: en.ecn.purdue.edu!noose.ecn.purdue.edu!samsung!munnari.oz.au!bruce!monu1!vaxc!apm279l From: apm279l@vaxc.cc.monash.edu.au Newsgroups: comp.sys.handhelds Subject: Saturn assembly language debugger Message-ID: <74583.2753b44c@vaxc.cc.monash.edu.au> Date: 28 Nov 90 01:57:48 GMT Organization: Computer Centre, Monash University, Australia Lines: 1166 The following is my "sim1" package. It is for debugging your saturn code before entry to your 28/48. I use the SASS assembler, so I've only run SASS-format code through it. It is possible there are a few bugs lurking around, so don't automatically assume a problem results from something in your code. Carry is set/cleared according to my understanding of what happens on the calculator (and correspondence with Alonzo). HOWEVER: it is possible some other instructions alter the carry, or that my understanding is wrong. At one stage, it was thought that gosubs alterred carry, I have been told that this is not the case, and gosubs in this code don't alter carry. I'm sorry I don't have time to make this code cope with more general cases, but I don't yet. It will work for almost all your code though, and I've found it quite easy to patch it's output C source to allow for some other cases anyway. For example, you can make up a C routine to simulate the effect of a jump to a part of your code which accesses RAM, if you know what a typical call might do. For more info, see the comments at the start of sim1.c Installation: There are 3 files in this package: SIM1.C, SIM1.H, LABELS.H I've not tar'd them as they are not too long, and this makes it easier to unpack on any machine. All you need to do is compile sim1.c, and run it. You are prompted for the input file (similar to the source you might feed into SASS), and an output file. You are then asked if you wish to step through your programme. If you answer in the affirmative, the output c source will include calls to a debugging module, and running it will be like running your code through a debugger. Cheers, and enjoy, Peter apm279l@vaxc.cc.monash.edu.au _ __ ,/^._/ ^\ { \-. ,-/~^/ `-/~ \. ( THE 48 ??!! } ___ / { A MERE ABACUS ,/ ,//| \ \ / ~ ~^\ MENTION IT NOT! | ,// =|H \*\ \,-+/^\ } ,// = =| P \ \ `-. _,/ ,// = = =|\ \ \ ~v/'~ ,// = = = =| \ 2 \ \ // = = = = =| \ 8 \ \ ||= = = = = =|\ \ S | | ||= = = = = =|= \ \ | | ||= = = = = =|= = \ \| | ||= = = = = =|= = = \ | / ||= = = = = =|= = = = \ || ||= = = = = =|= = = = = \|| ||= = = = = =|= = = = = =|| ||= = = = = =|= = = = = =|| ||= = = = =,/ \ = = = = =|| ||= = = =,/ \ = = = =|| ||= = =,/ \ = = =|| ||= =,/ \ = =|| ||=,/ \ =|| \|/ \|| ------------------------ %% BEGINNING OF SIM1.C %% ---------------------------- /* SIM1.C: A SATURN TO C CONVERTER... copyright (1990) by Peter Hawkins This programme is hereby placed in the public domain. Not to be sold in whole or part for financial gain. No liability will be accepted by the author. Do not remove this copyright notice. Parts of it are not-too-well written, and it produces messy code, but I don't really care! Peter Hawkins: apm279l@vaxc.cc.monash.edu.au Suggestions/comments/additions welcome. Flames to: bush@whitehouse.gov This version: Long is assumed to be four-byte, so all registers are 2-longs. a,b,c,d,d1,d0,st and p are all 64 bit, but only the relevant nybbles are used. The return-to-RPL address, stack pointer, d and b are used, but are initially set to arbitrary values. A jump to RPL is detected. Other jumps to memory are processed by the routine in labels.h (this allows you to add a table of "known" addresses of ROM subroutines.) The routine will warn you if you jump to RPL without restoring D,B D1 or D0. If you write to memory, this *is not* done, instead, a message is displayed to say what was written and where. Similarly, You are prompted for memory contents when you read from memory *unless* the routine in labels.h detects a read from a "known" location (eg stack). The commands sethex and setdec are not implemented yet - all operations are in HEX at this stage. If someone extends this send me a copy. I'd also like copies of any other extensions including additions to the labels.h file. I don't have time to do this stuff myself. The hardware status registors are not implemented, nor is IN or OUT; opcodes which use them are ignored. The opcodes used are Alonzo's improved set, with one additional command: "show_re[gisters]" which causes the contents of all registers to be printed whenever the programme reaches that point. If you select the "printout" mode at the prompt, the source code will behave like a (crudish) debugger. You can step through the "pseudo opcodes" one at a time, or several at a time, alter register contents, and the registors are displayed after each step. You've got some self-modifying code? bad luck; won't work sorry - this is a crude debugger - I don't think it's worth allowing for every eventuality at this stage. You may want to add to labels.h. Also, the screen functions are set up for a VT100, if you use another sort of terminal, just change the escape sequences (first routines in sim1.h) */ #include #include FILE *infd, *outfd; int inptr = 0,min,max,i,digit,bufptr,dotpos,ret_count=0,print_mode=0; char ch,field[4],r1[19],r2[4],buffer[50],label[20]; getbuff() { char ch1; bufptr = 0; buffer[bufptr] = 0; /* in case blank line or comment only */ dotpos = 0; while ( (!feof(infd)) && ((ch1=fgetc(infd)) != 10)) { if (ch1 == 59) { while (fgetc(infd) != 10); if (bufptr) break; } else { if ((ch1 > 31) || (ch1 == 9)) buffer[bufptr++] = ch1; if (ch1 == '.') dotpos = bufptr; if( ch1 == ':' ) { fprintf(outfd,"\n"); buffer[bufptr] = 0; fprintf(outfd,"%s\n",buffer); if (print_mode) fprintf(outfd,"printf(%c%s\\n%c);\n",34,buffer,34); bufptr = 0; dotpos = 0; } } } while ((bufptr > 0)&&(buffer[bufptr-1] < 33)) bufptr--; /*strip trailing junk */ buffer[bufptr] = 0; /* terminate string */ bufptr = 0; } char gtchar() /* finds & returns to next non-junk char, or end of string */ { char ch1; ch1 = 1; while ( (ch1 != 0) && ((ch1=buffer[bufptr++]) < 33 )); return ch1; } int get_token() { #define num_3_tokens 18 static char token_table3[num_3_tokens][3] = { "pop","clr","inc","dec","add","sub","and","rln","rrn", "srn","srb","sln","neg","not","nop","brz","ret","or." }; #define num_4_tokens 19 static char token_table4[num_4_tokens][4] = { "move","swap","push","clrb","setb","call","jump","breq", "brne","brgt","brlt","brge","brle","brbc","brbs","brcc", "brcs","brnz","retz"}; #define num_5_tokens 11 static char token_table5[num_5_tokens][5] = { "reteq","retne","retgt","retlt","retge","retle","retbc", "retbs","retcc","retcs","retnz"}; #define num_7_tokens 3 static char token_table7[num_7_tokens][7] = { "retsetc","retclrc","show_re"}; int pos1,token,i; pos1 = bufptr; if (dotpos) { bufptr = dotpos; for (i = 0; i < 4; ++i) field[i] = 0; field[0]=buffer[bufptr++]; if ((buffer[bufptr] > 31) && (field[0] < 58) && (buffer[bufptr] < 58)) field[1] = buffer[bufptr++]; else if (((field[0] == 'w') && (buffer[bufptr] == 'p')) || ((field[0] == 'x') && (buffer[bufptr] == 's'))) field[1] = buffer[bufptr++]; else if (field[0] == 'p') { i = 1; while (buffer[bufptr] > 31) field[i++] = buffer[bufptr++]; } } else strcpy(field,"def"); token = -1; for (i = 0; i < num_7_tokens; ++i) { if (!strncmp(&buffer[pos1],&token_table7[i][0],7)) token =i+num_5_tokens+num_4_tokens+num_3_tokens; } if (token >= 0) { if (!dotpos) bufptr += 7; return (token); } for (i = 0; i < num_5_tokens; ++i) { if (!strncmp(&buffer[pos1],&token_table5[i][0],5)) token =i+num_4_tokens+num_3_tokens; } if (token >= 0) { if (!dotpos) bufptr += 5; return (token); } for (i = 0; i < num_4_tokens; ++i) { if (!strncmp(&buffer[pos1],&token_table4[i][0],4)) token = i+num_3_tokens; } if (token >= 0) { if (!dotpos) bufptr += 4; return (token); } token = 99; for (i = 0; i < num_3_tokens; ++i) { if (!strncmp(&buffer[pos1],&token_table3[i][0],3)) token = i; } if (!dotpos) bufptr += 3; return (token); } main() { char filenm[20],pr_ans; int tokn; printf("Input file name> "); scanf("%s",filenm); if(!(infd = fopen(filenm,"r"))) { printf("error opening %s as input\n",filenm); exit(0); } printf("Output file name> "); scanf("%s",filenm); outfd = fdopen(creat(filenm,0),"w"); printf("Do you want %s to step through? n/y:",filenm); scanf("%s",&pr_ans); if (pr_ans == 'y' || pr_ans == 'Y') print_mode=1; fprintf(outfd,"#include %csim1.h%c\n\nmain()\n{\n\n#include%clabels.h%c\nset_pmasks();\n\ncls();\n\n",34,34,34,34); while (!feof(infd)) { getbuff(); if (gtchar()) { bufptr--; if (print_mode) fprintf(outfd,"getstep(%c%s%c);\n",34,buffer,34); switch (tokn = get_token()) { case 0: {fprintf(outfd,"pop();"); break;} case 1: {getr1(); fprintf(outfd,"clr(mask_%s,%s);",field,r1); break;} case 2: {getr1(); fprintf(outfd,"inc(mask_%s,%s);",field,r1); break;} case 3: {getr1(); fprintf(outfd,"dec(mask_%s,%s);",field,r1); break;} case 4: {getr1r2(); fprintf(outfd,"add(mask_%s,%s,%s);",field,r1,r2); break;} case 5: {getr1r2(); fprintf(outfd,"sub(mask_%s,%s,%s);",field,r1,r2); break;} case 6: {getr1r2(); fprintf(outfd,"and(mask_%s,%s,%s);",field,r1,r2); break;} case 7: {getr1(); fprintf(outfd,"rln(mask_%s,%s);",field,r1); break;} case 8: {getr1(); fprintf(outfd,"rrn(mask_%s,%s);",field,r1); break;} case 9: {getr1(); fprintf(outfd,"srn(mask_%s,%s);",field,r1); break;} case 10: {getr1(); fprintf(outfd,"srb(mask_%s,%s);",field,r1); break;} case 11: {getr1(); fprintf(outfd,"sln(mask_%s,%s);",field,r1); break;} case 12: {getr1(); fprintf(outfd,"neg(mask_%s,%s);",field,r1); break;} case 13: {getr1(); fprintf(outfd,"not(mask_%s,%s);",field,r1); break;} case 14: break; case 15: {getr1(); getlbl(); fprintf(outfd,"if (!(%s[0] & mask_%s[0]) || (!(%s[1] & mask_%s[1]))) {carry=1; goto %s;} else carry=0;\n",r1,field,r1,field,label); break;} case 16: {fprintf(outfd,"goto goreturn;"); break;} case 17: {getr1r2(); fprintf(outfd,"or(mask_%s,%s,%s);",field,r1,r2); break;} case 18: { getr1r2(); if (!strcmp(r2,"pc")) fprintf(outfd,"return_flag=0;tmp[1]=%s[1]&mask_a[1]; goto jump_mem;",r1); else { if (r1[0] == '@') fprintf(outfd,"input(%c%s%c,mask_%s,%s,%s);",34,field,34,field,&r1[1],r2); else if (r2[0] == '@') fprintf(outfd,"output(%c%s%c,mask_%s,%s,%s);",34,field,34,field,r1,&r2[1]); else fprintf(outfd,"move(mask_%s,%s,%s);",field,r1,r2); } break; } case 19: { getr1r2(); if (r1[0] == '@') { fprintf(outfd,"input(%c%s%c,mask_%s,%s,tmp); ",34,field,34,field,&r1[1]); strcpy(r1,"tmp"); } if (r2[0] == '@') { fprintf(outfd,"input(%c%s%c,mask_%s,tmp,%s); ",34,field,34,field,&r2[1]); strcpy(r2,"tmp"); } fprintf(outfd,"swap(mask_%s,%s,%s);",field,r1,r2); break; } case 20: {fprintf(outfd,"push();"); break;} case 21: {getr1r2(); fprintf(outfd,"%s[1]=%s[1]&(~(1L<<(%s[1]&mask_1[1])));",r2,r2,r1); break;} case 22: {getr1r2(); fprintf(outfd,"%s[1]=%s[1]|(1L<<(%s[1]&mask_1[1]));",r2,r2,r1); break;} case 23: {getlbl(); fprintf(outfd,"stack[stkptr--] = 0X%05X; goto %s; ret_%05X:",ret_count,label,ret_count); ret_count++; break;} case 24: {getlbl(); fprintf(outfd,"goto %s;",label); break;} case 25: {getr1r2(); getlbl(); branch("==",label); break;} case 26: {getr1r2(); getlbl(); branch("!=",label); break;} case 27: {getr1r2(); getlbl(); branch("> ",label); break;} case 28: {getr1r2(); getlbl(); branch("< ",label); break;} case 29: {getr1r2(); getlbl(); branch(">=",label); break;} case 30: {getr1r2(); getlbl(); branch("<=",label); break;} case 31: {getr1r2(); getlbl(); fprintf(outfd,"if ((~%s[1])&(1L<<(%s[1]&mask_1[1]))) {carry=1; goto %s;} else carry=0;",r2,r1,label); break;} case 32: {getr1r2(); getlbl(); fprintf(outfd,"if(%s[1]&(1L<<(%s[1]&mask_1[1]))) {carry=1; goto %s;} else carry=0;",r2,r1,label); break;} case 33: {getlbl(); fprintf(outfd,"if (!carry) goto %s;",label); break;} case 34: {getlbl(); fprintf(outfd,"if (carry) goto %s;",label); break;} case 35: {getr1(); getlbl(); fprintf(outfd,"if ((%s[0]&mask_%s[0])||(%s[1]&mask_%s[1])) {carry=1; goto %s;} else carry=0;",r1,field,r1,field,label); break;} case 36: {getr1(); fprintf(outfd,"if (!(%s[0] & mask_%s[0]) || !(%s[1] & mask_%s[1]))) {carry=1; goto %s;} else carry=0;",r1,field,r1,field); break;} case 37: {getr1r2(); branch("==","goreturn"); break;} case 38: {getr1r2(); branch("!=","goreturn"); break;} case 39: {getr1r2(); branch("> ","goreturn"); break;} case 40: {getr1r2(); branch("< ","goreturn"); break;} case 41: {getr1r2(); branch(">=","goreturn"); break;} case 42: {getr1r2(); branch("<=","goreturn"); break;} case 43: {getr1r2(); fprintf(outfd,"if ((~%s[1])&(1L<<(%s[1]&mask_1[1]))) {carry=1; goto goreturn;} else carry=0;",r2,r1); break;} case 44: {getr1r2(); fprintf(outfd,"if (%s[1]&(1L<<(%s[1]&mask_1[1]))) {carry=1; goto goreturn;} else carry=0;",r2,r1); break;} case 45: {fprintf(outfd,"if (!carry) goto goreturn;"); break;} case 46: {fprintf(outfd,"if (carry) goto goreturn;"); break;} case 47: {getr1(); fprintf(outfd,"if ((%s[0] & mask_%s[0])||(%s[1] & mask_%s[1])) {carry=1; goto goreturn;} else carry=0;",r1,field,r1,field); break;} case 48: {fprintf(outfd,"carry=1; goto goreturn;"); break;} case 49: {fprintf(outfd,"carry=0; goto goreturn;"); break;} case 50: {fprintf(outfd,"printf(%c\\n%c); show_regs();",34,34); break;} default: fprintf(outfd,"printf(%cUnknown operation: %s\\n%c);",34,buffer,34); } if (!print_mode) fprintf(outfd,"%c/* %s */\n",9,buffer); } } if (ret_count) { fprintf(outfd,"\n\ngoreturn: switch(stack[++stkptr] & mask_a[1])\n {\n"); for (i = 0;i < ret_count; ++i) fprintf(outfd," case 0X%05X: goto ret_%05X;\n",i,i); fprintf(outfd," case 0xfffff: {printf(%cERROR: you've pushed/popped return stack\\n%c); exit(0);}\n",34,34); fprintf(outfd," }\n\n"); } fprintf(outfd,"}\n"); fflush(outfd); fclose(outfd); fclose(infd); } getr1() { int j; char ch1; for (j = 0; j < 4; j++) r1[j] = 0; ch1=gtchar(); for (j = 0; ((ch1 != ',') && (j < 3)); j++) {r1[j] = ch1; ch1=gtchar();} } getr1r2() { int j,k; char ch1; for (j = 0; j < 19; j++) r1[j] = 0; for (j = 0; j < 4 ; j++) r2[j] = 0; ch1=gtchar(); for (j = 0; ch1 != ','; j++) {r1[j] = ch1; ch1=gtchar();} if (r1[0] < 58) /* constant (not register) */ { if ( (r1[0] == '$') || (r1[0] == '#') ) fprintf(outfd,"constmp(mask_%s,0x%sL); ",field,&r1[1]); else fprintf(outfd,"constmp(mask_%s,%sL); ",field,r1); strcpy(r1,"tmp"); r1[3] = 0; } ch1=gtchar(); for (j = 0; ((ch1 > 0) && (ch1 != ',') && (j < 3)); j++) {r2[j] = ch1; ch1=gtchar();} } getlbl() { int lblptr; char ch1; if ((ch1 = gtchar()) == 64) { strcpy(label,"_at_"); lblptr = 4; } else { lblptr = 0; bufptr--; } strcpy(&label[lblptr],&buffer[bufptr]); } branch( char *condit, char *lbl) { if (!strcmp(condit,"==")) { fprintf(outfd,"if (((%s[0]&mask_%s[0])%s(%s[0]&mask_%s[0]))&&",r1,field,condit,r2,field); fprintf(outfd,"((%s[1]&mask_%s[1])%s(%s[1]&mask_%s[1]))) ",r1,field,condit,r2,field); } else if (!strcmp(condit,"!=")) { fprintf(outfd,"if (((%s[0]&mask_%s[0])%s(%s[0]&mask_%s[0]))||",r1,field,condit,r2,field); fprintf(outfd,"((%s[1]&mask_%s[1])%s(%s[1]&mask_%s[1]))) ",r1,field,condit,r2,field); } else if ((!strcmp(condit,">="))||(!strcmp(condit,"<="))) { /* ruddy heck!! what a test!! any better ideas???? */ fprintf(outfd,"if ((((mask_%s[0]) && ((%s[0]&mask_%s[0])%1s(%s[0]&mask_%s[0])))||",field,r1,field,condit,r2,field); fprintf(outfd,"((!mask_%s[0]) && ((%s[1]&mask_%s[1])%1s(%s[1]&mask_%s[1])))) ",field,r1,field,condit,r2,field); fprintf(outfd,"|| (((%s[0]&mask_%s[0])==(%s[0]&mask_%s[0]))&&",r1,field,r2,field); fprintf(outfd,"((%s[1]&mask_%s[1])==(%s[1]&mask_%s[1])))) ",r1,field,r2,field); } else { fprintf(outfd,"if (((mask_%s[0]) && ((%s[0]&mask_%s[0])%s(%s[0]&mask_%s[0])))||",field,r1,field,condit,r2,field); fprintf(outfd,"((!mask_%s[0]) && ((%s[1]&mask_%s[1])%s(%s[1]&mask_%s[1])))) ",field,r1,field,condit,r2,field); } fprintf(outfd,"{carry=1; goto %s;} else carry=0;",lbl); } -------------------------- %% END OF SIM1.C %% -------------------------------- ------------------------ %% BEGINNING OF SIM1.H %% ---------------------------- #include #include #include #define STRTYP 0x02a2c #define REATYP 0x02933 #define IMCTYP 0x02c96 #define ALGTYP 0x02ab8 #define PRGTYP 0x02d9d #define NAMTYP 0x02e48 #define LOCTYP 0x02e67 #define BINTYP 0x02a4e #define d0_init 0x000e9e52 /* any number, hopefully not required */ #define d1_init 0x000e9e54 /* top of display_stack */ #define st_init 0x00000000 #define b_init 0x76768576 #define d_init 0x29004976 /*now define contents of "known" locations (ie @d0, @d1...) */ #define RPL 0x000e9e53 /* address of next RPL ins */ #define ST0 (d1_init+0x100) /* pointer to stack level 0 */ #define ST1 (ST0 + 0x100) #define ST2 (ST1 + 0x100) #define ST3 (ST2 + 0x100) #define ST4 (ST3 + 0x100) /* now a few aliases */ #define mask_pa mask_p10 #define mask_pb mask_p11 #define mask_pc mask_p12 #define mask_pd mask_p13 #define mask_pe mask_p14 #define mask_pf mask_p15 typedef unsigned long reg_t[2]; reg_t tmp; reg_t a,b={0,b_init},c,d={0,d_init}; reg_t r0,r1,r2,r3,r4; reg_t d0={0,d0_init},d1={0,d1_init},pc={0,0},st={0,st_init},p={0,0}; unsigned char carry=0,stkptr=6,return_flag; unsigned long stack[7]={0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}; /* ------------------------------------------------------------------------- */ /* Screen functions for vt100 */ cls() /* clear screen */ { printf("%c[2J",27); } ebl() /* erase bottom line */ { bos(); printf("%c[2K",27); } tos() /* curser to top of screen */ { printf("%c[H",27); } bos() /* curser to bottom of screen */ { printf("%c[23;0H",27); } bold() /* bold text */ { printf("%c[1m",27); } norm() /* normal text */ { printf("%c[0m",27); } /* ------------------------------------------------------------------------- */ reg_t mask_1 = {0x00000000, 0x0000000f}; reg_t mask_2 = {0x00000000, 0x000000ff}; reg_t mask_3 = {0x00000000, 0x00000fff}; reg_t mask_4 = {0x00000000, 0x0000ffff}; reg_t mask_5 = {0x00000000, 0x000fffff}; reg_t mask_6 = {0x00000000, 0x00ffffff}; reg_t mask_7 = {0x00000000, 0x0fffffff}; reg_t mask_8 = {0x00000000, 0xffffffff}; reg_t mask_9 = {0x0000000f, 0xffffffff}; reg_t mask_10 = {0x000000ff, 0xffffffff}; reg_t mask_11 = {0x00000fff, 0xffffffff}; reg_t mask_12 = {0x0000ffff, 0xffffffff}; reg_t mask_13 = {0x000fffff, 0xffffffff}; reg_t mask_14 = {0x00ffffff, 0xffffffff}; reg_t mask_15 = {0x0fffffff, 0xffffffff}; reg_t mask_16 = {0xffffffff, 0xffffffff}; reg_t mask_w = {0xffffffff, 0xffffffff}; reg_t mask_a = {0x00000000, 0x000fffff}; reg_t mask_x = {0x00000000, 0x00000fff}; reg_t mask_s = {0xf0000000, 0x00000000}; reg_t mask_m = {0x0fffffff, 0xfffff000}; reg_t mask_b = {0x00000000, 0x000000ff}; reg_t mask_xs = {0x00000000, 0x00000f00}; reg_t mask_def= {0x00000000, 0x000fffff}; /* default - non .a defaults should be OK */ reg_t mask_p,mask_wp,mask_p1,mask_p2,mask_p3,mask_p4,mask_p5,mask_p6; reg_t mask_p7,mask_p8,mask_p9,mask_p10,mask_p11,mask_p12,mask_p13; reg_t mask_p14,mask_p15,mask_p16; set_pmasks() { short int i; p[1] &= mask_1[1]; p[0] = 0; if (p[1] < 8) { mask_p[0] = 0x00000000; mask_p[1] = 0x0000000f; mask_wp[0] = 0x00000000; mask_wp[1] = 0x0000000f; for (i = 0; i < p[1]; ++i) { mask_p[1] == (mask_p[1] << (4*i)); mask_wp[1] |= mask_p[1]; } } else { mask_p[0] = 0x0000000f; mask_p[1] = 0x00000000; mask_wp[0] = 0x0000000f; mask_wp[1] = 0x00000000; for (i = 0; i < p[1]-8; ++i) { mask_p[0] == (mask_p[0] << (4*i)); mask_wp[0] |= mask_p[0]; } } mask_n(mask_p1,1); mask_n(mask_p2,2); mask_n(mask_p3,3); mask_n(mask_p4,4); mask_n(mask_p5,5); mask_n(mask_p6,6); mask_n(mask_p7,7); mask_n(mask_p8,8); mask_n(mask_p9,9); mask_n(mask_p10,10); mask_n(mask_p11,11); mask_n(mask_p12,12); mask_n(mask_p13,13); mask_n(mask_p14,14); mask_n(mask_p15,15); mask_n(mask_p16,16); } mask_n(reg,n) reg_t reg; int n; { reg_t tmp1; int i; reg[0] = 0; reg[1] = 0; if (p[1] < 8) { for (i = p[1]; (i < 8)&&(i<(n+p[1])); ++i) reg[1] |= (0xf << (4*i)); if (i < (n+p[1])) {for (i = 0; (i < 8)&&(i<(n+p[1]-8)); ++i) reg[0] |= (0xf<< (4*i));} } else { for (i = p[1]; (i < 8)&&(i<(n+p[1])); ++i) reg[0] |= (0xf << (4*i)); } } move( mask, reg1, reg2) reg_t mask, reg1, reg2; { short int i; if (®1[0]==&pc[0]) printf("Ignoring instruction...\n"); else { if ((&mask[0]==&mask_def[0]) && ( (®1[0]==&r0[0])||(®2[0]==&r0[0]) ||(®1[0]==&r1[0])||(®2[0]==&r1[0]) ||(®1[0]==&r2[0])||(®2[0]==&r2[0]) ||(®1[0]==&r3[0])||(®2[0]==&r3[0]) ||(®1[0]==&r4[0])||(®2[0]==&r4[0]) )) {mask[0]=mask_w[0]; mask[1]=mask_w[1];} for (i = 0; i < 2; ++i) reg2[i] = (reg2[i] & (~mask[i])) | (reg1[i] & mask[i]); if (®2[0]==&p[0]) set_pmasks(); } } swap( mask, reg1, reg2) reg_t mask, reg1, reg2; { short int i; reg_t tmp1; if ((&mask[0]==&mask_def[0]) && ( (®1[0]==&r0[0])||(®2[0]==&r0[0]) ||(®1[0]==&r1[0])||(®2[0]==&r1[0]) ||(®1[0]==&r2[0])||(®2[0]==&r2[0]) ||(®1[0]==&r3[0])||(®2[0]==&r3[0]) ||(®1[0]==&r4[0])||(®2[0]==&r4[0]) )) {mask[0]=mask_w[0]; mask[1]=mask_w[1];} for (i = 0; i < 2; ++i) { tmp1[i] = (reg2[i] & (~mask[i])) | (reg1[i] & mask[i]); reg1[i] = (reg1[i] & (~mask[i])) | (reg2[i] & mask[i]); reg2[i] = tmp1[i]; } if (®2[0]==&p[0]) set_pmasks(); } push() { stack[stkptr--] = c[0] & mask_a[0]; } pop() { c[0] = ((c[0] & (~mask_a[0])) | (stack[stkptr++] & mask_a[0])); } clr( mask, reg1) reg_t mask, reg1; { short int i; for (i = 0; i < 2; i++) reg1[i] &= (~mask[i]); } and( mask, reg1, reg2) reg_t mask, reg1, reg2; { short int i; for (i = 0; i < 2; i++) reg2[i] = ((reg2[i] & (~mask[i])) | (reg2[i] & mask[i] & reg1[i])); } or( mask, reg1, reg2) reg_t mask, reg1, reg2; { short int i; for (i = 0; i < 2; i++) reg2[i] = ((reg2[i] & (~mask[i])) | ((reg2[i] |reg1[i]) & mask[i])); } inc( mask, reg1) reg_t mask, reg1; { reg_t tmp1; tmp1[0] = 0; tmp1[1] = 1; while (tmp1[1] && (!(tmp1[1] & mask[1]))) (tmp1[1] << 4); if (!tmp1[1]) { tmp1[0] = 1; while (tmp1[0] && (!(tmp1[0] & mask[0]))) (tmp1[0] << 4); } add(mask,tmp1,reg1); } dec( mask, reg1) reg_t mask, reg1; { reg_t tmp1; tmp1[0] = 0; tmp1[1] = 1; while (tmp1[1] && (!(tmp1[1] & mask[1]))) (tmp1[1] << 4); if (!tmp1[1]) { tmp1[0] = 1; while (tmp1[0] && (!(tmp1[0] & mask[0]))) (tmp1[0] << 4); } sub(mask,tmp1,reg1); } add( mask, reg1, reg2) reg_t mask, reg1, reg2; { unsigned long t; reg2[1] += (reg1[1] & mask[1]); if ( (((reg2[1] >> 4) + (reg1[1] & mask[1])) >> 4) & 0xf0000000 ) { t = reg2[0]; reg2[0] += ( (reg1[0]+1) & mask[0] ); carry = (t+((reg1[0]+1) & mask[0]) != reg2[0]); } else { t = reg2[0]; reg2[0] += ( reg1[0] & mask[0] ); carry = (t+(reg1[0] & mask[0]) != reg2[0]); } if (®2[0]==&p[0]) set_pmasks(); } sub( mask, reg1, reg2) reg_t mask, reg1, reg2; { unsigned long t; reg2[1] -= (reg1[1] & mask[1]); if ((reg2[1] & mask[1]) < (reg1[1] & mask[1])) { t = reg2[0]; reg2[0] -= ( (reg1[0]+1) & mask[0] ); carry = (t-((reg1[0]+1) & mask[0]) != reg2[0]); } else { t = reg2[0]; reg2[0] -= ( reg1[0] & mask[0] ); carry = (t-(reg1[0] & mask[0]) != reg2[0]); } if (®2[0]==&p[0]) set_pmasks(); } not( mask, reg1) reg_t mask, reg1; { carry = 0; reg1[0] = (reg1[0] & (~mask[0])) | ((~reg1[0]) & mask[0]); reg1[1] = (reg1[1] & (~mask[1])) | ((~reg1[1]) & mask[1]); } neg( mask, reg1) reg_t mask, reg1; { not(mask,reg1); dec(mask,reg1); } rrn( mask, reg1) reg_t mask, reg1; { long i,store; if (mask[1]) { for (i=0xfL; (!(mask[1] & i)); i = i << 4); store = reg1[1] & i; } else { for (i=0xfL; (!(mask[0] & i)); i = i < 4); store = reg1[0] & i; } while (store > 0xfL) store = store >> 4; srn(mask,reg1); if (store) { if (mask[0]) { for (i=0xf0000000L; (!(mask[0] & i)); i = i >> 4); while (!(store & i)) store = store << 4; reg1[0] |= store; } else { for (i=0xf0000000L; (!(mask[1] & i)); i = i >> 4); while (!(store & i)) store = store << 4; reg1[1] |= store; } } } rln( mask, reg1) reg_t mask, reg1; { long i,store; if (mask[0]) { for (i=0xf0000000L; (!(mask[0] & i)); i = i >> 4); store = reg1[0] & i; } else { for (i=0xf0000000L; (!(mask[1] & i)); i = i >> 4); store = reg1[1] & i; } while (store > 0xfL) store = store >> 4; sln(mask,reg1); if (store) { if (mask[1]) { for (i=0xfL; (!(mask[1] & i)); i = i << 4); while (!(store & i)) store = store << 4; reg1[1] |= store; } else { for (i=0xfL; (!(mask[0] & i)); i = i << 4); while (!(store & i)) store = store << 4; reg1[0] |= store; } } } srn( mask, reg1) reg_t mask, reg1; { reg_t tmp1; tmp1[1] = (((reg1[1] & mask[1]) >> 4L)|((reg1[0] & 0xfL) << 28L)) & mask[1]; tmp1[0] = (reg1[0] & mask[0]) >> 4L; reg1[0] = (reg1[0] & (~mask[0])) | (tmp1[0] & mask[0]); reg1[1] = (reg1[1] & (~mask[1])) | (tmp1[1] & mask[1]); } srb( mask, reg1) reg_t mask, reg1; { reg_t tmp1; tmp1[1] = (((reg1[1] & mask[1]) >> 1L)|((reg1[0] & 0x1L) << 31L)) & mask[1]; tmp1[0] = (reg1[0] & mask[0]) >> 1L; reg1[0] = (reg1[0] & (~mask[0])) | (tmp1[0] & mask[0]); reg1[1] = (reg1[1] & (~mask[1])) | (tmp1[1] & mask[1]); } sln( mask, reg1) reg_t mask, reg1; { reg_t tmp1; tmp1[1] = ((reg1[1] & mask[1]) << 4L) & mask[1]; tmp1[0] = (((reg1[0] & mask[0]) << 4L)|((reg1[1] & 0xf0000000L) >> 28L)) & mask[0]; reg1[0] = (reg1[0] & (~mask[0])) | (tmp1[0] & mask[0]); reg1[1] = (reg1[1] & (~mask[1])) | (tmp1[1] & mask[1]); } constmp(mask, cons) reg_t mask; long cons; { short int i; i = 0; while ((1 << i) && !((1 << i) & mask[1])) i += 4; if (!(1 << (i-8))) while ((1 << (i-8)) && !((1 << (i-8)) & mask[0])) i += 4; tmp[1] = (mask[1] & ( cons << i )); tmp[0] = (mask[0] & ( cons >> (8-i) )); } show_regs() { int i; char strng1[17],strng2[17]; printf("-------------------------------------------------------------------------------\n"); printf("| a=%08X%08X b=%08X%08X c=%08X%08X d=%08X%08X |\n",a[0],a[1],b[0],b[1],c[0],c[1],d[0],d[1]); printf("| d0 = %05X, d1 = %05X, status = %04X, p = %1X, carry %s |\n",d0[1]&mask_a[1],d1[1]&mask_a[1],st[1]&mask_4[1],p[1],(carry) ? "set " :"clear"); printf("-------------------------------------------------------------------------------\n"); } input(fld, mask, reg1, reg2) reg_t mask, reg1, reg2; char fld[3]; { char instr[17],str1[9],str2[17]; int i; if((mask[0]==mask_a[0]) && (mask[1]==mask_a[1])) /* getting an address? */ { switch (reg1[1]&mask_a[1]) /* is it known? */ { case d0_init: {reg2[1]=(reg2[1] & (~mask[1])) | (RPL & mask[1]); return; break; } case d1_init: {reg2[1]=(reg2[1] & (~mask[1])) | (ST0 & mask[1]); return; break; } case (5 +d1_init): {reg2[1]=(reg2[1] & (~mask[1])) | (ST1 &mask[1]); return; break; } case (10+d1_init): {reg2[1]=(reg2[1] & (~mask[1])) | (ST2 & mask[1]); return; break; } case (15+d1_init): {reg2[1]=(reg2[1] & (~mask[1])) | (ST3 & mask[1]); return; break; } case (20+d1_init): {reg2[1]=(reg2[1] & (~mask[1])) | (ST4 & mask[1]); return; break; } case ST0: {intype(mask,reg2,1); return; break;} case ST1: {intype(mask,reg2,1); return; break;} case ST2: {intype(mask,reg2,2); return; break;} case ST3: {intype(mask,reg2,3); return; break;} case ST4: {intype(mask,reg2,4); return; break;} case (ST0+5): {printf("Input from Stack[0]+5: "); break;} case (ST0+10): {printf("Input from Stack[0]+10: "); break;} case (ST1+5): {printf("Input from Stack[1]+5: "); break;} case (ST1+10): {printf("Input from Stack[1]+10: "); break;} case (ST2+5): {printf("Input from Stack[2]+5: "); break;} case (ST2+10): {printf("Input from Stack[2]+10: "); break;} case (ST3+5): {printf("Input from Stack[3]+5: "); break;} case (ST3+10): {printf("Input from Stack[3]+10: "); break;} case (ST4+5): {printf("Input from Stack[4]+5: "); break;} case (ST4+10): {printf("Input from Stack[4]+10: "); break;} } } for (i = 0; i < 16; ++i) instr[i] = 48; instr[17] = 0; for (i = 0; i < 8 && !( (1<<(4*i)) & mask[1]); ++i); if (i == 8) for (i = 8;i < 16 & !( (1<<((4*i)-32)) & mask[0]); ++i); printf("Input [%3s] field (in hex) stored at %05X: ",fld,(reg1[1] & mask_a[1]) ); scanf("%s",str2); printf("\n"); strncpy(&instr[16-i-strlen(str2)],str2,strlen(str2)); strncpy(str1,instr,8); str1[8]=0; reg2[0] = (reg2[0] & (~mask[0])) | (strtoul(str1,NULL,16) & mask[0]); reg2[1] = (reg2[1] & (~mask[1])) | (strtoul(&instr[8],NULL,16) & mask[1]); } output(fld, mask, reg1, reg2) reg_t mask, reg1, reg2; char fld[3]; { if (mask[0] && mask[1]) printf("[%s] field of @[%05X] <= %x%0x\n",fld,reg2[1]&mask_a[1],reg1[0]&mask[0],reg1[1]&mask[1]); else if (mask[0] && !mask[1]) printf("[%s] field of @[%05X] <= %x\n",fld,reg2[1]&mask_a[1],reg1[0]&mask[0]); else printf("[%s] field of @[%05X] is now %x\n",fld,reg2[1]&mask_a[1],reg1[1]&mask[1]); } intype(mask,reg2,lvl) reg_t mask, reg2; int lvl; { int i; printf("Input type of object in level %d of display:\n\n (0) String\n (1) Real\n (2) Inline machine code\n (3) Algebraic obj\n (4) Programme\n (5) Global Name\n (6) Local Name\n (7) Binary Integer\n",lvl); scanf("%d",&i); switch (i) { case 0: {reg2[1]=(reg2[1] & (~mask[1])) | (STRTYP & mask[1]); break;} case 1: {reg2[1]=(reg2[1] & (~mask[1])) | (REATYP & mask[1]); break;} case 2: {reg2[1]=(reg2[1] & (~mask[1])) | (IMCTYP & mask[1]); break;} case 3: {reg2[1]=(reg2[1] & (~mask[1])) | (ALGTYP & mask[1]); break;} case 4: {reg2[1]=(reg2[1] & (~mask[1])) | (PRGTYP & mask[1]); break;} case 5: {reg2[1]=(reg2[1] & (~mask[1])) | (NAMTYP & mask[1]); break;} case 6: {reg2[1]=(reg2[1] & (~mask[1])) | (LOCTYP & mask[1]); break;} case 7: {reg2[1]=(reg2[1] & (~mask[1])) | (BINTYP & mask[1]); break;} default: printf("error, unknown type\n"); } printf("\n"); } getstep(char *cmd) { char cnt[5]; static int step_count=1; printf ("%s\n",cmd); if (!(--step_count)) { tos(); bold(); show_regs(); bos(); printf("\n%c%c%c clr,set,qui,n-steps: ",9,9,9); norm(); scanf("%s",cnt); while ((!strcmp(cnt,"clr"))||(!strcmp(cnt,"set"))) { if(!strcmp(cnt,"clr")) { cls(); bos(); printf ("%s",cmd); printf ("\n"); /* for some reason, I need to do it this way on my term */ } else { bold(); printf("Enter name of register (a,b,c,d,d0,d1,st,p,car): "); norm(); scanf("%s",cnt); ebl(); if (!strcmp(cnt,"car")) { bold(); printf("Set/Clear? (s/c)"); norm(); scanf("%c",cnt); if (cnt[0]==115) carry=1; else carry=0; } else if (!strcmp(cnt,"p")) { bold(); printf("Enter HEX value (1 nybble): "); norm(); scanf("%1x",&p[1]); set_pmasks(); } else if (!strcmp(cnt,"st")) { bold(); printf("Enter HEX value (4 nybbles): "); norm(); scanf("%4x",&st[1]); } else if (!strcmp(cnt,"d0")) { bold(); printf("Enter new value (in HEX) (5 nybbles): "); norm(); scanf("%5x",&d0[1]); } else if (!strcmp(cnt,"d1")) { bold(); printf("Enter new value (in HEX) (5 nybbles): "); norm(); scanf("%5x",&d1[1]); } else if (!strcmp(cnt,"a")) { bold(); printf("Enter new value (in HEX) (16 nyb incl leading 0s): "); norm(); scanf("%16x",&a[0],&a[1]); } else if (!strcmp(cnt,"b")) { bold(); printf("Enter new value (in HEX) (16 nyb incl leading 0s): "); norm(); scanf("%16x",&b[0],&b[1]); } else if (!strcmp(cnt,"c")) { bold(); printf("Enter new value (in HEX) (16 nyb incl leading 0s): "); norm(); scanf("%16x",&c[0],&c[1]); } else if (!strcmp(cnt,"d")) { bold(); printf("Enter new value (in HEX) (16 nybs incl leading 0s): "); norm(); scanf("%16x",&d[0],&d[1]); } else printf("Illegal register name - ignored"); printf("\n"); } tos(); bold(); show_regs(); bos(); printf("\n%c%c%c clr,set,qui,n-steps: ",9,9,9); norm(); scanf("%s",cnt); } if (!strcmp(cnt,"qui")) { cls(); tos(); exit(0); } ebl(); step_count=strtol(cnt,NULL,10); if (!step_count) step_count = 1; } } -------------------------- %% END OF SIM1.H %% -------------------------------- ---------------------- %% BEGINNING OF LABELS.H %% ---------------------------- cls(); bos(); goto start_prg; jmp_at_a: tmp[1] = a[1]; return_flag = 0; goto jump_mem; jmp_at_c: tmp[1] = c[1]; return_flag = 0; goto jump_mem; jump_mem: switch (tmp[1]&mask_a[1]) { case RPL: { printf("programme returned to RPL\n"); if (p) printf("%%%WARNING%%% you have not set p to 0,%c\n",7); if (b[1] != b_init) printf("%%%WARNING%%% you have not restored b,%c\n",7); if (d0[1] != d0_init + 5) printf("%%%WARNING%%% you have not restored d0,%c\n",7); if (d1[1] != d1_init + (d[1]-d_init)*5) printf("%%%WARNING%%% d1 and d are no longer consistent,%c\n",7); break; } default: printf("programme jumped to memory location %5x\n",tmp[1] & mask_a[1]); } if (!return_flag) exit(0); else printf("%%%WARNING%%% programme continuing without executing routine at%5x%c\n",tmp[1] & mask_a[1],7); start_prg: /* ------------------------------------------------------------------------- */ ------------------------- %% END OF PACKAGE %% ------------------------------