#include #include #include "glovar.h" /*****************************************************************/ /* Computing Science MSc Dissertation */ /* `newogg' oggin Interpreter */ /* By Lydia L W Wong (C) August 1990 */ /* University of Stirling */ /*****************************************************************/ /* this file called newa.c contains functions which cope with */ /* displaying data on windows. */ /*****************************************************************/ static char codegroup[3][8]={"group 1","group 2","group 3"}; extern octalcode writeoct(); /* convert integer to octal no. */ extern void assl_g1(); /* display group 1 instruction. */ extern void assl_g3(); /* display group 3 instruction. */ extern char grp1code[][4]; /* group 1 mnemonics */ extern char grp2code[][4]; /* group 2 mnemonics */ extern char grp3code[][4]; /* group 3 mnemonics */ /*****************************************************************/ /* output trailer message and terminate the program. */ /*****************************************************************/ void terminate() { endwin(); printf("End of program Run"); exit(0); } /*****************************************************************/ /* show user which line lacks case selection and stop running. */ /*****************************************************************/ void Caseerror(n) int n; /* line number of the program */ { mvwprintw(user_win,1,1, "Missing case limb: line %d\n", n); wrefresh(user_win); terminate(); } /*****************************************************************/ /* show an unrecognised opcode and where it is and stop running. */ /*****************************************************************/ void nonrecognise(n,d,g) int n; /* address of opcode */ int d; /* unrecognised opcode */ int g; /* group of opcode */ { mvwprintw(user_win,1,0,"Unrecognised opcode %6o\n",d); mvwprintw(user_win,2,0,"in group %d at location %o.\n",g,n); wrefresh(user_win); terminate(); } /*****************************************************************/ /* show user error message when access location over memory range*/ /*****************************************************************/ void erroradd(address) int address; /* access location */ { mvwprintw(user_win, 4,1, "invalid address %4d",address); terminate(); } /*****************************************************************/ /* display user messages at the beginning. */ /*****************************************************************/ void message() { WINDOW *win; initscr(); /* initialise screen */ win = newwin(20,70,0,3); box(win,'*','*'); mvwprintw(win,2,23,"%s","WRITTEN BY DR D BUDGEN"); mvwprintw(win,3,20,"%s","SIMULATED BY LYDIA L W WONG"); mvwprintw(win,4,21,"%s","(C)1990, Written 15-Aug-90"); mvwprintw(win,8,2,"%s","This program is used to run the octal code of oggin assembly"); mvwprintw(win,9,2,"%s","language. On the screen, you will see changes to registers and"); mvwprintw(win,10,2,"%s","memory after each instruction has been executed."); mvwprintw(win,11,2,"%s","Locations are highlighted when significant changes occur or"); mvwprintw(win,12,2,"%s","special attention is required. You will also see an"); mvwprintw(win,13,2,"%s","explanation and comments for each instruction. "); mvwprintw(win,15,2,"%s","Now if you are ready, press any key to start the program."); mvwprintw(win,16,2,"%s","I hope you enjoy using it. Good luck! "); wrefresh(win); getch(); endwin(); } /*****************************************************************/ /* display main oggin machine startup title screen. */ /*****************************************************************/ title() { char ch; WINDOW *win1; initscr(); /* initialise screen */ win1= newwin(20,71,1,1); box(win1,'*','*'); wattron(win1,A_BOLD); mvwprintw(win1,1,2,"%s","TTTTTT H H EEEEE"); mvwprintw(win1,2,2,"%s"," TT H H E "); mvwprintw(win1,3,2,"%s"," TT HHHHHH EEEE "); mvwprintw(win1,4,2,"%s"," TT H H E "); mvwprintw(win1,5,2,"%s"," TT H H EEEEE"); mvwprintw(win1,7,2,"%s"," OOO GGG GGG II N N"); mvwprintw(win1,8,2,"%s"," O O G G G G II NN N"); mvwprintw(win1,9,2,"%s"," O O G G II N N N"); mvwprintw(win1,10,2,"%s"," O O G GGG G GGG II N N N"); mvwprintw(win1,11,2,"%s"," O O G G G G II N NN"); mvwprintw(win1,12,2,"%s"," OOO GGG GGG II N N"); mvwprintw(win1,14,2,"%s", " M M A CCC H H II N N EEEEE"); mvwprintw(win1,15,2,"%s", " MM MM A A C C H H II NN N E"); mvwprintw(win1,16,2,"%s", " M MM M AAAAA C HHHHHH II N N N EEEE "); mvwprintw(win1,17,2,"%s", " M M A A C C H H II N N N E"); mvwprintw(win1,18,2,"%s", " M M A A CCC H H II N NN EEEEE"); wattroff(win1,A_BOLD); wrefresh(win1); endwin(); } /*****************************************************************/ /* input access location which is used to compute the place in */ /* pad that is going to be highlighted. */ /*****************************************************************/ void updatepad(address,str) int address; /* access location */ octalcode str; /* octal no. output as a string */ { int pady; /* line number of pad */ int padx; /* colunm number of pad */ int line_y; /* start line of pad to be displayed */ int j; /* location number */ int l; /* line number of location */ pady = (address / 4); padx = (address % 4) * 8; wattron(pad,A_STANDOUT); mvwprintw(pad, pady, padx, "%s", str.A); wattroff(pad,A_STANDOUT); if (pady < 10) line_y = 0; else if (pady > 245 ) line_y = 246; else line_y = pady - 3; j =(line_y * 4); for (l = 0; l <= 10 ;l++) { mvwprintw(loca_win, l, 0, "%4o", j); j = (j + 4 ); } pnoutrefresh(pad, line_y, 0, 13, 7, 22, 36); wnoutrefresh(loca_win); } /*****************************************************************/ /* input access location; compute the highlighted place in pad */ /* and clear the highlight function. */ /*****************************************************************/ void clearpad(address,str) int address; /* access location in memory */ octalcode str; /* octal no. output as a string */ { int pady; /* line number of pad */ int padx; /* colunm number of pad */ int line_y;/* first line to be displayed of pad*/ pady = (address / 4); padx = (address % 4) * 8; mvwprintw(pad, pady, padx, "%s", str.A); if (pady < 10) line_y = 0; else if (pady > 245 ) line_y = 246; else line_y = pady - 3; pnoutrefresh(pad, line_y, 0, 13, 7, 22, 36); } /*****************************************************************/ /* create windows and initialise some of them. */ /*****************************************************************/ void buildwin() { winp = newwin(1,6,1,0); wini = newwin(1,6,1,12); wina = newwin(1,6,1,23); wins = newwin(1,6,1,34); winx = newwin(1,6,1,45); winc = newwin(1,6,1,56); winn = newwin(1,6,1,67); pad = newpad(256,36); assl_win = newwin(3,15,6,17); expl_win = newwin(7,13,6,61); user_win = newwin(3,32,19,42); loca_win = newwin(10,4,13,0); assl_t = newwin(1,32,4,0); expl_t = newwin(8,17,5,42); mm_t = newwin(1,11,11,0); comm_win = newwin(5,32,14,42); mvwprintw(assl_t,0,0,"INSTRUCTIONS :"); mvwprintw(mm_t,0,0,"MAIN MEMORY"); mvwprintw(expl_t,0,0,"EXPLANATION :"); mvwprintw(expl_t,2,0,"OCTAL CODE :"); mvwprintw(expl_t,3,0,"FUNCTION CODE :"); mvwprintw(expl_t,4,0,"OPCODE GROUP :"); mvwprintw(expl_t,5,0,"ADDRESSING MODE :"); mvwprintw(expl_t,6,0,"OPERAND :"); mvwprintw(expl_t,7,0,"ACCESS LOCATION :"); wnoutrefresh(assl_t); wnoutrefresh(expl_t); wnoutrefresh(mm_t); } /*****************************************************************/ /* fill loca_win with addresses and the pad with data in memory. */ /*****************************************************************/ void buildpad() { int j; /* location number */ int i; /* counter of For loop */ int pady; /* line number of pad */ int padx; /* colunm number of pad */ octalcode str; /* octal no. output as a string */ j = 0; for (i=0; i<=10; i++) { mvwprintw(loca_win,i,0,"%4o",j); j = (j + 4); } wnoutrefresh(loca_win); for (i=0; i<=1023; i++) { pady = i / 4; padx = (i % 4) * 8; str = writeoct(mm.A[i]); mvwprintw(pad, pady, padx, "%s%s", str.A," "); } pnoutrefresh(pad,0,0,13,7,22,36); } /*****************************************************************/ /* get value of next instruction,decode it and show it on screen */ /*****************************************************************/ void lookahead() { instructiongroup opcodegroup; /* instruction group */ boolean errorstatus; /* true = location over range */ int bits12_14; /* value of the top 3 bits */ int operand; /* value of operand bits */ int signal; /* value either 1 or 0 */ ingroup1 opcodeg1; /* function code of group 1 */ ingroup2 opcodeg2; /* function code of group 2 */ ingroup3 opcodeg3; /* function code of group 3 */ addressingmodes addressmode; /* addressing mode */ int mdr; /* value of each instruction */ readcycle(pcnew, &mdr, &errorstatus); if (errorstatus) erroradd(pcnew); decoding(mdr, &opcodegroup, &bits12_14, &operand); signal = 1; switch (opcodegroup) { case group1: dogroup1(mdr - operand, &opcodeg1, &addressmode, operand,signal); break; case group2: dogroup2(mdr, &opcodeg2,signal); break; case group3: dogroup3(bits12_14, mdr - operand, &opcodeg3, operand,signal); break ; default: Caseerror(Line); } } /*****************************************************************/ /* move values of registers to windows and display them. */ /*****************************************************************/ void show_wins() { octalcode str; /* octal no. output as a string */ str = writeoct(pc); mvwprintw(winp,0,0, "%s", str.A); str = writeoct(mdr); mvwprintw(wini,0,0, "%s", str.A); str = writeoct(acc); mvwprintw(wina,0,0, "%s", str.A); str = writeoct(sp); mvwprintw(wins,0,0, "%s", str.A); str = writeoct(ir); mvwprintw(winx,0,0, "%s", str.A); mvwprintw(winc,0,0, "%1d%1d%1d%1d", psw.c,psw.n,psw.z,psw.v); pc = pcnew; str = writeoct(pc); mvwprintw(winn,0,0, "%s", str.A); wnoutrefresh(assl_t); wnoutrefresh(assl_win); wnoutrefresh(expl_win); wnoutrefresh(winp); wnoutrefresh(wini); wnoutrefresh(wina); wnoutrefresh(wins); wnoutrefresh(winx); wnoutrefresh(winc); wnoutrefresh(winn); wnoutrefresh(comm_win); doupdate(); } /*****************************************************************/ /* display message for user and get a character from terminal. */ /*****************************************************************/ void show_user(ch) char *ch; /* character got from terminal */ { mvwaddstr(user_win,1,1,"Press q for exit and any other"); mvwaddstr(user_win,2,1,"keys for next instruction:"); mvwaddch(user_win,2,28,' '); wrefresh(user_win); (*ch) = mvwgetch(user_win,2,28); } /*****************************************************************/ /* clear windows before next instruction cycle. */ /*****************************************************************/ void clearwins() { wclear(winp); wclear(wini); wclear(wina); wclear(wins); wclear(winx); wclear(winc); wclear(winn); wclear(assl_win); wclear(expl_win); wclear(loca_win); wclear(comm_win); } /*****************************************************************/ /* loop for executing each instruction cycle, displaying the */ /* the result on screen and redrawing the screen for next cycle, */ /* until end of program. */ /*****************************************************************/ void inst_cycle() /* this is refered to as `inst()' in comments */ { instructiongroup opcodegroup; /* instruction group */ boolean errorstatus; /* true = location over range */ int bits12_14; /* value of the top 3 bits */ int operand; /* value of operand bits */ int blockaddress; /* block address of file read */ int blocksize; /* size of block being read */ int signal; /* value either 1 or 0 */ octalcode str; /* a string of octal number */ ogginword binary; /* binary number of 16 bits */ int i; /* counter of For loop */ char ch; /* character got from terminal*/ ingroup1 opcodeg1; /* function code of group 1 */ ingroup2 opcodeg2; /* function code of group 2 */ ingroup3 opcodeg3; /* function code of group 3 */ addressingmodes addressmode; /* addressing mode */ boolean endofprogram; /* true = function code is stp*/ static instructiongroup oldgrp;/* previous instruction group */ static ingroup1 oldg1; /* previous function code of group 1 */ static ingroup2 oldg2; /* previous function code of group 2 */ static ingroup3 oldg3; /* previous function code of group 3 */ static int oldrand; /* value of operand bits of previous instruction */ static char oldsign; /* previous descriptor of addressing mode */ endofprogram = false; do { if (pc != 0) { switch (oldgrp) { case group1 : assl_g1(oldg1,oldsign,oldrand,0); break; case group2 : mvwprintw(assl_win,0,0,"%s",grp2code[oldg2]); break; case group3 : assl_g3(oldg3,oldrand,0); break; } } readcycle(pc, &mdr, &errorstatus); if (errorstatus) erroradd(pc); decoding(mdr, &opcodegroup, &bits12_14, &operand); str = writeoct(mdr); mvwprintw(expl_win,1,0,"%s",str.A); mvwprintw(expl_win,5,0,"%o",operand); integertooggin(mdr,&binary); for (i=15; i>=0; i--) mvwprintw(assl_t,0,16+15-i,"%1d",binary.A[i]); oldgrp = opcodegroup; mvwprintw(expl_win,3,0,"%s",codegroup[opcodegroup]); signal = 0; switch (opcodegroup) { case group1: oldrand = operand; oldsign = dogroup1(mdr - operand, &opcodeg1, &addressmode, operand,signal); oldg1 = opcodeg1; if (addressmode == immediate) mvwprintw(expl_win,6,0,"none"); else{ if (opcodeg1 == sta) str = writeoct(acc); else str = writeoct(mm.A[location]); mvwprintw(expl_win,6,0,"%o",location); updatepad(location,str); } break ; case group2: dogroup2(mdr, &opcodeg2,signal); oldg2 = opcodeg2; if ((opcodeg2 == psh)||(opcodeg2 == pul)||(opcodeg2 == rts) || (opcodeg2 == sti) || (opcodeg2 == rir)) { mvwprintw(expl_win,6,0,"%o",location); str = writeoct(mm.A[location]); updatepad(location,str); } else mvwprintw(expl_win,6,0,"none"); if ((opcodeg2 == rtt) || (opcodeg2 == trp)) { mvwprintw(expl_win,6,0,"%o & %o",location,loca_1); str = writeoct(mm.A[location]); updatepad(location,str); str = writeoct(mm.A[loca_1]); updatepad(loca_1,str); wstandout(winn); } if ((opcodeg2 == asr) || (opcodeg2 == asl) || (opcodeg2 == lsr) || (opcodeg2 == lsl) || (opcodeg2 == trp) || (opcodeg2 == rtt)) wstandout(winc); if ((opcodeg2 == sti) || (opcodeg2 == rir) || (opcodeg2 == spi) || (opcodeg2 == inc)) wstandout(winx); break ; case group3: oldrand = operand; dogroup3(bits12_14, mdr - operand, &opcodeg3, operand,signal); oldg3 = opcodeg3; wstandout(winc); wstandout(winn); break ; default: Caseerror(Line); } lookahead(); if (opcodeg2 == stp) mvwprintw(assl_win,2,0," "); show_wins(); show_user(&ch); if((ch == 'q') || (ch == 'Q')) break; switch(opcodegroup) { case group1 : if (opcodeg1 == sta ) str = writeoct(acc); else str = writeoct(mm.A[location]); if (addressmode != immediate) clearpad(location,str); if ((opcodeg1 == sta) || (opcodeg1 == lda)) wstandend(wina); if (opcodeg1 == ldi) wstandend(winx); if ((opcodeg1 == jsr) || (opcodeg1 == jmp)) wstandend(winn); break; case group2 : if ((opcodeg2 == psh) || (opcodeg2 == pul) || ((opcodeg2) == rts) || (opcodeg2 == sti) || (opcodeg2 == rir)) { str = writeoct(mm.A[location]); clearpad(location,str); } if ((opcodeg2 == rtt) || (opcodeg2 == trp)) { str = writeoct(mm.A[location]); clearpad(location,str); str = writeoct(mm.A[loca_1]); clearpad(loca_1,str); wstandend(winn); } if ((opcodeg2 == psh) || (opcodeg2 == pul) || (opcodeg2 == neg)) wstandend(wina); if ((opcodeg2 == rts) || (opcodeg2 == rtt)) wstandend(winn); if ((opcodeg2 == asr) || (opcodeg2 == asl) || (opcodeg2 == lsr) || (opcodeg2 == lsl) || (opcodeg2 == trp) || (opcodeg2 == rtt)) wstandend(winc); if ((opcodeg2 == sti) || (opcodeg2 == rir) || (opcodeg2 == spi) || (opcodeg2 == inc)) wstandend(winx); if (opcodeg2 == spi) wstandend(wins); break; case group3 : wstandend(winc); wstandend(winn); break; } oldacc = acc; clearwins(); if (opcodeg2 == stp) endofprogram = true; } while (!(endofprogram)); } /* ** End of newa.c */