From e6ad30063b3e24e2ba692b5ec5a7418b9ccfdeb8 Mon Sep 17 00:00:00 2001 From: Andreas Scherer Date: Mon, 7 Oct 2013 15:30:15 +0200 Subject: [PATCH] =?UTF-8?q?MMIX=202009=20=E2=80=94=20Release=202013-10-07.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mmix-arith.w | 3 +++ mmix-config.w | 2 +- mmix-doc.w | 14 +++++++------- mmix-pipe.w | 18 ++++++++++-------- mmix-sim.w | 46 ++++++++++++++++++++++++---------------------- mmixal.w | 6 +++--- mmmix.w | 6 ++++-- 7 files changed, 52 insertions(+), 43 deletions(-) diff --git a/mmix-arith.w b/mmix-arith.w index 28efcba..a94226b 100644 --- a/mmix-arith.w +++ b/mmix-arith.w @@ -12,6 +12,7 @@ @s ff TeX @s bool normal @q unreserve a C++ keyword @> @s xor normal @q unreserve a C++ keyword @> +@s bignum int @* Introduction. The subroutines below are used to simulate 64-bit \MMIX\ arithmetic on an old-fashioned 32-bit computer---like the one the author @@ -487,6 +488,8 @@ it is tiny and either (i)~it is inexact or (ii)~the underflow trap is enabled. The |fpack| routine sets |U_BIT| in |exceptions| if and only if the result is tiny, |X_BIT| if and only if the result is inexact. @^underflow@> +@^tininess@> +@^accuracy loss@> @d X_BIT (1<<8) /* floating inexact */ @d Z_BIT (1<<9) /* floating division by zero */ diff --git a/mmix-config.w b/mmix-config.w index 1b13b48..7e6325e 100644 --- a/mmix-config.w +++ b/mmix-config.w @@ -758,7 +758,7 @@ int_stages[ld]=int_stages[st]=int_stages[frem]=2; for (j=0;j<256;j++) stages[j]=int_stages[int_op[j]]; @ The |int_op| conversion table is similar to the |internal_op| array of -the \\{MMIX\_pipe} routine, but it replaces |divu| by |div|, +the \\{MMIX\_run} routine, but it replaces |divu| by |div|, |fsub| by |fadd|, etc. @= diff --git a/mmix-doc.w b/mmix-doc.w index ca8aeeb..aed607a 100644 --- a/mmix-doc.w +++ b/mmix-doc.w @@ -89,7 +89,7 @@ have made significant contributions. @^Hennessy, John LeRoy@> @^Sites, Richard Lee@> -@ A programmer's introduction to \MMIX\ appears in ``Volume~1 Fascicle~1,'' +@ A programmer's introduction to \MMIX\ appears in ``Volume~1, Fascicle~1,'' @^Fascicle 1@> a booklet containing tutorial material that will ultimately appear in the fourth edition of {\sl The Art of Computer Programming}. @@ -344,7 +344,7 @@ into $\mm_8[\$2+17]$. @.STB@> The least significant byte of register~X is stored into byte $\mm[\rY+\rZ]$ or $\mm[\rY+\zz]$. An integer overflow exception occurs if -@.overflow@> +@^overflow@> \$X is not between $-128$ and $+127$. (We will discuss overflow and other kinds of exceptions later.) @@ -411,7 +411,7 @@ The sum $\rY+\rZ$ or $\rY+\zz$ is placed into register~X using signed, two's complement arithmetic. An integer overflow exception occurs if the sum is $\ge2^{63}$ or $<-2^{63}$. (We will discuss overflow and other kinds of exceptions later.) -@.overflow@> +@^overflow@> \bull\ @.ADDU@> @@ -705,7 +705,7 @@ exclusive-or is used to combine the bits. Thus we obtain a matrix product over the field of two elements instead of a Boolean matrix product. This operation can be used to construct hash functions, among many other things. (The hash functions aren't bad, but they are not ``universal'' in the -sense of exercise 6.4--72.) +sense of {\sl Sorting and Searching}, exercise 6.4--72.) @^matrices of bits@> @^Boolean multiplication@> @@ -2239,7 +2239,7 @@ and place the result in~rZZ\null. A~subsequent When a forced trap occurs on a store instruction because of memory protection failure, the settings of rYY and rZZ are undefined. They do not necessarily -correspond to the virtual address rY and octabyte to be stored rZ +correspond to the virtual address rY and the octabyte to be stored rZ that are supplied to a trip handler after a tripped store instruction, because a forced trap aborts its instruction as soon as possible. @@ -2661,7 +2661,7 @@ by Advanced Micro Devices, in the processors of their Am29000 series---a family of computers whose instructions have essentially the format `OP~X~Y~Z' used by~\MMIX.] @^Ditzel, David Roger@> -@^McClellan, Hubert Rae, Jr.@> +@^McLellan, Hubert Rae, Jr.@> Limited versions of\/ \MMIX, having fewer registers, can also be envisioned. For example, we might have only 32 local registers $\l[0]$, $\l[1]$, @@ -2710,7 +2710,7 @@ of the current value and the new value. (A~program should say \ @^privileged operations@> diff --git a/mmix-pipe.w b/mmix-pipe.w index 0043924..b7f4536 100644 --- a/mmix-pipe.w +++ b/mmix-pipe.w @@ -24,9 +24,8 @@ A lot of subtle things can happen when instructions are executed in parallel. Therefore this simulator ranks among the most interesting and instructive programs in the author's experience. The author has tried his best to make everything correct \dots\ but the chances for error are great. Anyone who -discovers a bug is therefore urged to report it as soon as possible to -\.{knuth-bug@@cs.stanford.edu}; then the program will be as useful as -possible. Rewards will be paid to bug-finders! (Except for bugs in version~0.) +discovers a bug is therefore urged to report it as soon as possible; +please see \.{http:/\kern-.1em/mmix.cs.hm.edu/bugs/} for instructions. It sort of boggles the mind when one realizes that the present program might someday be translated by a \CEE/~compiler for \MMIX\ and used to simulate @@ -35,6 +34,8 @@ someday be translated by a \CEE/~compiler for \MMIX\ and used to simulate @ This high-performance prototype of \MMIX\ achieves its efficiency by means of ``pipelining,'' a technique of overlapping that is explained for the related \.{DLX} computer in Chapter~3 of Hennessy \char`\&\ Patterson's +@^Hennessy, John LeRoy@> +@^Patterson, David Andrew@> book {\sl Computer Architecture\/} (second edition). Other techniques such as ``dynamic scheduling'' and ``multiple issue,'' explained in Chapter~4 of that book, are used too. @@ -202,7 +203,7 @@ bypass the library names here. @ The |MMIX_init()| routine should be called exactly once, after |MMIX_config()| has done its work but before the simulator starts to execute -any programs. Then |MMIX_run| can be called as often as the user likes. +any programs. Then |MMIX_run()| can be called as often as the user likes. @s octa int @@ -3849,6 +3850,7 @@ fact does help us: We know that the flusher coroutine will not be aborted until it has run to completion. Some machines, such as the Alpha 21164, have an additional cache between +@^Alpha computers@> the S-cache and memory, called the B-cache (the ``backup cache''). A B-cache could be simulated by extending the logic used here; but such extensions of the present program are left to the interested reader. @@ -4347,7 +4349,7 @@ static octa phys_addr @,@,@[ARGS((octa,octa))@]; static octa phys_addr(virt,trans) octa virt,trans; {@+octa t; - t=oandn(trans,page_mask); /* zero out the |ynp| fields of a PTE */ + t=oandn(trans,page_mask); /* zero out the \\{ynp} fields of a PTE */ return oplus(t,oand(virt,page_mask)); } @@ -4993,7 +4995,7 @@ data->state=ld_ready; if (data->i==preld || data->i==prest) goto fin_ex;@+else sleep; @ If a |prest| instruction makes it to the hot seat, -we have been assured by the user of |PREST| that the current +we have been assured by the user of \.{PREST} that the current values of bytes in virtual addresses |data->y.o-(data->xx&-Dcache->bb)| through |data->y.o+(data->xx&(Dcache->bb-1))| are irrelevant. Hence we can pretend that we know they are zero. This @@ -5419,7 +5421,7 @@ tail->noted=false; if (inst_ptr.o.l==breakpoint.l && inst_ptr.o.h==breakpoint.h) breakpoint_hit=true; -@ The commands |RESUME|, |SAVE|, |UNSAVE|, and |SYNC| should not have +@ The commands \.{RESUME}, \.{SAVE}, \.{UNSAVE}, and \.{SYNC} should not have nonzero bits in the positions defined here. @= @@ -5652,7 +5654,7 @@ if (verbose&issue_bit) { @d RESUME_AGAIN 0 /* repeat the command in rX as if in location $\rm rW-4$ */ @d RESUME_CONT 1 /* same, but substitute rY and rZ for operands */ -@d RESUME_SET 2 /* set r[X] to rZ */ +@d RESUME_SET 2 /* set register \$X to rZ */ @d RESUME_TRANS 3 /* install $\rm(rY,rZ)$ into IT-cache or DT-cache, then |RESUME_AGAIN| */ @d pack_bytes(a,b,c,d) ((((((unsigned)(a)<<8)+(b))<<8)+(c))<<8)+(d) diff --git a/mmix-sim.w b/mmix-sim.w index 1cc5b47..cb6995c 100644 --- a/mmix-sim.w +++ b/mmix-sim.w @@ -58,7 +58,7 @@ count field of~rU may increase by~1 (modulo~$2^{47}$) for each instruction. @ To run this simulator, assuming \UNIX/ conventions, you say `\.{mmix} \ \.{progfile} \.{args...}', where \.{progfile} is an output of the \.{MMIXAL} assembler, -\.{args...} is a sequence of optional command-line arguments passed +\.{args...} is a sequence of optional command line arguments passed to the simulated program, and \ is any subset of the following: @^command line arguments@> @@ -121,7 +121,7 @@ end of file when standard input has been defined in any other way. simulators, instead of actually doing a simulation. \bull \.{-?}\quad Print the ``\.{Usage}'' message, which summarizes -the command-line options. +the command line options. \smallskip\noindent The author recommends \.{-t2} \.{-l} \.{-L} for initial offline debugging. @@ -134,7 +134,7 @@ even if \.{-i} and \.{-I} were not specified on the command line. @ In interactive mode, the user is prompted `\.{mmix>}' and a variety of @.mmix>@> -commands can be typed online. Any command-line option can be given +commands can be typed online. Any command line option can be given in response to such a prompt (including the `\.-' that begins the option), and the following operations are also available: @@ -436,13 +436,13 @@ example below.) the global registers are initialized according to the \.{GREG} statements in the \.{MMIXAL} program, and \$255 is set to the numeric equivalent of~\.{Main}. Local register~\$0 is -initially set to the number of {\it command-line arguments\/}; and +initially set to the number of {\it command line arguments\/}; and @^command line arguments@> local register~\$1 points to the first such argument, which -is always a pointer to the program name. Each command-line argument is a +is always a pointer to the program name. Each command line argument is a pointer to a string; the last such pointer is M$_8[\$0\ll3+\$1]$, and M$_8[\$0\ll3+\$1+8]$ is zero. (Register~\$1 will point to an octabyte in -\.{Pool\_Segment}, and the command-line strings will be in that segment +\.{Pool\_Segment}, and the command line strings will be in that segment too.) Location M[\.{Pool\_Segment}] will be the address of the first unused octabyte of the pool segment. @@ -753,7 +753,7 @@ mem_node* new_mem() } @ Initially we start with a chunk for the pool segment, since -the simulator will be putting command-line information there before +the simulator will be putting command line information there before it runs the program. @= @@ -1055,7 +1055,7 @@ G=zbyte;@+ L=0; for (j=G+G;j<256+256;j++,ll++,aux.l+=4) read_tet(), ll->tet=tet; inst_ptr.h=(ll-2)->tet, inst_ptr.l=(ll-1)->tet; /* \.{Main} */ (ll+2*12)->tet=G<<24; -g[255]=incr(aux,12*8); /* we will |UNSAVE| from here, to get going */ +g[255]=incr(aux,12*8); /* we will \.{UNSAVE} from here, to get going */ @* Loading and printing source lines. The loaded program generally contains cross references to the lines @@ -1819,10 +1819,10 @@ if (!l) panic("No room for the local registers"); @.No room...@> cur_round=ROUND_NEAR; -@ In operations like |INCH|, we want |z| to be the |yz| field, +@ In operations like \.{INCH}, we want |z| to be the |yz| field, shifted left 48 bits. We also want |y| to be register~X, which has -previously been placed in |b|; then |INCH| can be simulated as if -it were |ADDU|. +previously been placed in |b|; then \.{INCH} can be simulated as if +it were \.{ADDU}. @= { @@ -2193,7 +2193,7 @@ case CSWAP: case CSWAPI: w.l&=-8;@+ll=mem_find(w); } goto check_ld; -@ The |GET| command is permissive, but |PUT| is restrictive. +@ The \.{GET} command is permissive, but \.{PUT} is restrictive. @= case GET:@+if (yy!=0 || zz>=32) goto illegal_inst; @@ -2267,7 +2267,7 @@ case POP:@+if (xx!=0 && xx<=L) y=l[(O+xx-1)&lring_mask]; goto sync_L; @ To complete our simulation of \MMIX's register stack, we need -to implement |SAVE| and |UNSAVE|. +to implement \.{SAVE} and \.{UNSAVE}. @= case SAVE:@+if (xx= { @@ -2648,7 +2648,7 @@ if (rop==RESUME_SET) { z=g[rZ]; } -@ We don't want to count the |UNSAVE| that bootstraps the whole process. +@ We don't want to count the \.{UNSAVE} that bootstraps the whole process. @= if (sclock.l || sclock.h || !resuming) { @@ -2916,7 +2916,7 @@ int main(argc,argv) return g[255].l; /* provide rudimentary feedback for non-interactive runs */ } -@ Here we process the command-line options; when we finish, |*cur_arg| +@ Here we process the command line options; when we finish, |*cur_arg| should be the name of the object file to be loaded and simulated. We assume that |argv[0]| is never null. (The author believes strongly that @@ -2945,7 +2945,7 @@ are harmless while interacting. @= void scan_option @,@,@[ARGS((char*,bool))@];@+@t}\6{@> void scan_option(arg,usage) - char *arg; /* command-line argument (without the `\.-') */ + char *arg; /* command line argument (without the `\.-') */ bool usage; /* should we exit with usage note if unrecognized? */ { register int k; @@ -2982,7 +2982,7 @@ void scan_option(arg,usage) case 'D': @;@+return; default:@+if (usage) { fprintf(stderr, - "Usage: %s progfile command-line-args...\n",myself); + "Usage: %s progfile command line-args...\n",myself); @.Usage: ...@> for (k=0;usage_help[k][0];k++) fprintf(stderr,usage_help[k]); exit(-1); @@ -3253,8 +3253,8 @@ switch (cur_disp_mode) { }@+break; } -@ Here we essentially simulate a |PUT| command, but we simply |break| -if the |PUT| is illegal or privileged. +@ Here we essentially simulate a \.{PUT} command, but we simply |break| +if the \.{PUT} is illegal or privileged. @= if (k>=9 && k!=rI) { @@ -3362,7 +3362,7 @@ void show_breaks(p) if (p->right) show_breaks(p->right); } -@ We put pointers to the command-line strings in +@ We put pointers to the command line strings in M$_8[\.{Pool\_Segment}+8*(k+1)]$ for $0\le k<|argc|$; the strings themselves are octabyte-aligned, starting at M$_8[\.{Pool\_Segment}+8*(|argc|+2)]$. The location of the first free @@ -3399,7 +3399,9 @@ if (dump_file) { } @ The special option `\.{-D}' can be used to prepare binary files -needed by the \MMIX-in-\MMIX\ simulator of Section 1.4.3\'{}. This option +needed by the \MMIX-in-\MMIX\ simulator of Section 1.4.3\'{}. (See +{\sl The Art of Computer Programming}, Volume~1, Fascicle~1.) This option +@^Fascicle 1@> puts big-endian octa\-bytes into a given file; a location~$l$ is followed by one or more nonzero octabytes M$_8[l]$, M$_8[l+8]$, M$_8[l+16]$, \dots, followed by zero. The simulated simulator knows how to load programs diff --git a/mmixal.w b/mmixal.w index d22ea6f..88c5ab5 100644 --- a/mmixal.w +++ b/mmixal.w @@ -681,10 +681,10 @@ data assembled for each byte position; but the general rule ``do not load two things into the same byte'' is safest.) All locations that do not receive assembled data are initially zero, except that the loading routine will put register stack data into -segment~3, and the operating system may put command-line data and +segment~3, and the operating system may put command line data and debugger data into segment~2. (The rudimentary \MMIX\ operating system starts a program -with the number of command-line arguments in~\$0, and a pointer to +with the number of command line arguments in~\$0, and a pointer to the beginning of an array of argument pointers in~\$1.) Segments 2 and 3 should not get assembled data, unless the user is a true hacker who is willing to take the risk that such data @@ -1129,7 +1129,7 @@ register Char *p,*q; /* the place where we're currently scanning */ @ The next several subroutines are useful for preparing a listing of the assembled results. In such a listing, which the user can request -with a command-line option, we fill the leftmost 19 columns with +with a command line option, we fill the leftmost 19 columns with a representation of the output that has been assembled from the input in the buffer. Sometimes the assembled output requires more than one line, because we have room to output only a tetrabyte per line. diff --git a/mmmix.w b/mmmix.w index b5281a9..6b4d33c 100644 --- a/mmmix.w +++ b/mmmix.w @@ -163,10 +163,12 @@ FILE *prog_file; @* Binary input to memory. When the program file was dumped by {\mc MMIX-SIM}, it -has the simple format discussed in exercise 1.4.3$'$--20 of the \MMIX\ fascicle. +has the simple format discussed in exercise 1.4.3$'$--20 of the \MMIX\ fascicle +[{\sl The Art of Computer Programming}, Volume~1, Fascicle~1]. +@^Fascicle 1@> @^binary files@> @^segments@> -In this case we assume that the user's program has text, data, pool, and stack +We assume that such a program has text, data, pool, and stack segments, as in the conventions of that book. We load it into four $2^{32}$-byte pages of physical memory, one for each segment; page zero of