take_risc.w
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:7k
源码类别:

通讯编程

开发平台:

Visual C++

  1. % This file is part of the Stanford GraphBase (c) Stanford University 1993
  2. @i boilerplate.w %<< legal stuff: PLEASE READ IT BEFORE MAKING ANY CHANGES!
  3. @i gb_types.w
  4. deftitle{TAKE_,RISC}
  5. prerequisite{GB_,GATES}
  6. @* Introduction. This demonstration program uses graphs
  7. constructed by the |risc| procedure in the {sc GB_,GATES} module to produce
  8. an interactive program called .{take_risc}, which multiplies and divides
  9. small numbers the slow way---by simulating the behavior of
  10. a logical circuit, one gate at a time.
  11. The program assumes that UNIX/ conventions are being used. Some code in
  12. sections listed under `UNIX/ dependencies' in the index might need to change
  13. if this program is ported to other operating systems.
  14. def<#1>{$langle${rm#1}$rangle$}
  15. To run the program under UNIX/, say `.{take_risc} <trace>', where <trace>
  16. is nonempty if and only if you want the machine computations to
  17. be printed out.
  18. The program will prompt you for two numbers, and it will use the simulated
  19. RISC machine to compute their product and quotient. Then it will ask
  20. for two more numbers, and so on.
  21. @ Here is the general layout of this program, as seen by the CEE/ compiler:
  22. @^UNIX dependencies@>
  23. @p
  24. #include "gb_graph.h" /* the standard GraphBase data structures */
  25. #include "gb_gates.h" /* routines for gate graphs */
  26. @h@#
  27. @<Global variables@>@;
  28. main(argc,argv)
  29.   int argc; /* the number of command-line arguments */
  30.   char *argv[]; /* an array of strings containing those arguments */
  31. {
  32.   trace=(argc>1? 8: 0); /* we'll show registers 0--7 if tracing */
  33.   if ((g=risc(8L))==NULL) {
  34.     printf("Sorry, I couldn't generate the graph (trouble code %ld)!n",
  35.       panic_code);
  36.     return(-1);
  37.   }
  38.   printf("Welcome to the world of microRISC.n");
  39.   while(1) {
  40.     @<Prompt for two numbers; |break| if unsuccessful@>;
  41.     @<Use the RISC machine to compute the product, |p|@>;
  42.     printf("The product of %ld and %ld is %ld%s.n",m,n,p,
  43.         o?" (overflow occurred)":"");
  44.     @<Use the RISC machine to compute the quotient and remainder,
  45.         |q| and~|r|@>;
  46.     printf("The quotient is %ld, and the remainder is %ld.n",q,r);
  47.   }
  48.   return 0; /* normal exit */
  49. }
  50. @ @<Glob...@>=
  51. Graph *g; /* graph that defines a simple RISC machine */
  52. long o,p,q,r; /* overflow, product, quotient, remainder */
  53. long trace; /* number of registers to trace */
  54. long m,n; /* numbers to be multiplied and divided */
  55. char buffer[100]; /* input buffer */
  56. @ @d prompt(s)
  57.     {@+printf(s);@+fflush(stdout); /* make sure the user sees the prompt */
  58.       if (fgets(buffer,99,stdin)==NULL) break;@+}
  59. @<Prompt...@>=
  60. prompt("nGimme a number: ");
  61. step0:if (sscanf(buffer,"%ld",&m)!=1) break;
  62. step1:if (m<=0) {
  63.   prompt("Excuse me, I meant a positive number: ");
  64.   if (sscanf(buffer,"%ld",&m)!=1) break;
  65.   if (m<=0) break;
  66. }
  67. while (m>0x7fff) {
  68.   prompt("That number's too big; please try again: ");
  69.   if (sscanf(buffer,"%ld",&m)!=1) goto step0; /* |step0| will |break| out */
  70.   if (m<=0) goto step1;
  71. }
  72. @<Now do the same thing for |n| instead of |m|@>;
  73. @ @<Now do the same thing for |n| instead of |m|@>=
  74. prompt("OK, now gimme another: ");
  75. if (sscanf(buffer,"%ld",&n)!=1) break;
  76. step2:if (n<=0) {
  77.   prompt("Excuse me, I meant a positive number: ");
  78.   if (sscanf(buffer,"%ld",&n)!=1) break;
  79.   if (n<=0) break;
  80. }
  81. while (n>0x7fff) {
  82.   prompt("That number's too big; please try again: ");
  83.   if (sscanf(buffer,"%ld",&n)!=1) goto step0; /* |step0| will |break| out */
  84.   if (n<=0) goto step2;
  85. }
  86. @* A RISC program. Here is the little program we will run on the
  87. little computer. It consists mainly of a subroutine called |tri|,
  88. which computes the value of the ternary operation $xlfloor
  89. y/zrfloor$, assuming that $yge0$ and $z>0$; the inputs $x,y,z$
  90. appear in registers $1,2,3$, respectively, and the exit address is
  91. assumed to be in register~7.  As special cases we can compute the
  92. product $xy$ (letting $z=1$) or the quotient $lfloor y/zrfloor$
  93. (letting $x=1$). When the subroutine returns, it leaves the result in
  94. register~4; it also leaves the value $(ybmod z)-z$ in register~2.
  95. Overflow will be set if and only if the true result was not between
  96. $-2^{15}$ and $2^{15}-1$, inclusive.
  97. It would not be difficult to modify the code to make it work with unsigned
  98. 16-bit numbers, or to make it deliver results with 32 or 48 or perhaps
  99. even 64 bits of precision.
  100. @d div 7 /* location `|div|' in the program below */
  101. @d mult 10 /* location `|mult|' in the program below */
  102. @d memry_size 34 /* the number of instructions in the program below */
  103. @<Glob...@>=
  104. unsigned long memry[memry_size]={
  105.            /* a ``read-only memory'' used by |run_risc| */
  106.   0x2ff0, /* |start:| $\{r2}=m$ (contents of next word) */
  107.   0x1111, /* (we will put the value of |m| here, in |memry[1]|) */
  108.   0x1a30, /* quad$\{r1}=n$ (contents of next word) */
  109.   0x3333, /* (we will put the value of |n| here, in |memry[3]|) */
  110.   0x7f70, /* quad&{jumpto} (contents of next word),
  111.                         $\{r7}={}$return address */
  112.   0x5555, /* (we will put either |mult| or |div| here, in |memry[5]|) */
  113.   0x0f8f, /* halt without changing any status bits */
  114.   0x3a21, /* |div:| $\{r3}=\{r1}$ */
  115.   0x1a01, /* quad$\{r1}=1$ */
  116.   0x0a12, /* quad|goto tri| (literally, |@t\{r0}@>+=2|) */
  117.   0x3a01, /* |mult:| $\{r3}=1$ */
  118.   0x4000, /* |tri:| $\{r4}=0$ */
  119.   0x5000, /* quad$\{r5}=0$ */
  120.   0x6000, /* quad$\{r6}=0$ */
  121.   0x2a63, /* quad|@t\{r2}@>-=@t\{r3}@>| */
  122.   0x0f95, /* quad|goto l2| */
  123.   0x3063, /* |l1:| |@t\{r3}@><<=1| */
  124.   0x1061, /* quad|@t\{r1}@><<=1| */
  125.   0x6ac1, /* quad|if| (overflow) $\{r6}=1$ */
  126.   0x5fd1, /* quad|@t\{r5}@>++| */
  127.   0x2a63, /* |l2:| |@t\{r2}@>-=@t\{r3}@>| */
  128.   0x039b, /* quad|if| ($ge0$) |goto l1| */
  129.   0x0843, /* quad|goto l4| */
  130.   0x3463, /* |l3:| |@t\{r3}@>>>=1| */
  131.   0x1561, /* quad|@t\{r1}@>>>=1| */
  132.   0x2863, /* |l4:| |@t\{r2}@>+=@t\{r3}@>| */
  133.   0x0c94, /* quad|if| ($<0$) |goto l5| */
  134.   0x4861, /* quad|@t\{r4}@>+=@t\{r1}@>| */
  135.   0x6ac1, /* quad|if| (overflow) $\{r6}=1$ */
  136.   0x2a63, /* quad|@t\{r2}@>-=@t\{r3}@>| */
  137.   0x5a41, /* |l5:| |@t\{r5}@>--| */
  138.   0x0398, /* quad|if| ($ge0$) |goto l3| */
  139.   0x6666, /* quad|if| (\{r6}) force overflow (literally |@t\{r6}@>>>=4|) */
  140.   0x0fa7}; /* quad|return|
  141.                  (literally, $\{r0}=\{r7}$, preserving overflow) */
  142. @ @<Use the RISC machine to compute the product, |p|@>=
  143. memry[1]=m;
  144. memry[3]=n;
  145. memry[5]=mult;
  146. run_risc(g,memry,memry_size,trace);
  147. p=(long)risc_state[4];
  148. o=(long)risc_state[16]&1; /* the overflow bit */
  149. @ @<Use the RISC machine to compute the quotient and remainder, |q| and~|r|@>=
  150. memry[5]=div;
  151. run_risc(g,memry,memry_size,trace);
  152. q=(long)risc_state[4];
  153. r=((long)(risc_state[2]+n))&0x7fff;
  154. @* Index. Finally, here's a list that shows where the identifiers of this
  155. program are defined and used.