/[gxemul]/trunk/doc/technical.html
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/doc/technical.html

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8 - (hide annotations)
Mon Oct 8 16:18:19 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/html
File size: 21755 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.777 2005/06/12 12:31:52 debug Exp $
==============  RELEASE 0.3.3.1  ==============

20050609	Adding simple MIPS IPIs (to dev_mp).
20050611	Adding an ugly hack to track down low-reference bugs
		(define TRACE_NULL_CRASHES, or configure --tracenull).
		Other minor updates.
20050612	Adding a dummy evbmips mode.

==============  RELEASE 0.3.3.2  ==============


1 dpavlin 8 <html><head><title>GXemul documentation: Technical details</title>
2     <meta name="robots" content="noarchive,nofollow,noindex"></head>
3 dpavlin 4 <body bgcolor="#f8f8f8" text="#000000" link="#4040f0" vlink="#404040" alink="#ff0000">
4     <table border=0 width=100% bgcolor="#d0d0d0"><tr>
5     <td width=100% align=center valign=center><table border=0 width=100%><tr>
6     <td align="left" valign=center bgcolor="#d0efff"><font color="#6060e0" size="6">
7     <b>GXemul documentation:</b></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
8     <font color="#000000" size="6"><b>Technical details</b>
9     </font></td></tr></table></td></tr></table><p>
10 dpavlin 2
11     <!--
12    
13 dpavlin 8 $Id: technical.html,v 1.51 2005/06/04 22:47:49 debug Exp $
14 dpavlin 2
15     Copyright (C) 2004-2005 Anders Gavare. All rights reserved.
16    
17     Redistribution and use in source and binary forms, with or without
18     modification, are permitted provided that the following conditions are met:
19    
20     1. Redistributions of source code must retain the above copyright
21     notice, this list of conditions and the following disclaimer.
22     2. Redistributions in binary form must reproduce the above copyright
23     notice, this list of conditions and the following disclaimer in the
24     documentation and/or other materials provided with the distribution.
25     3. The name of the author may not be used to endorse or promote products
26     derived from this software without specific prior written permission.
27    
28     THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
29     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31     ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
32     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38     SUCH DAMAGE.
39    
40     -->
41    
42    
43     <a href="./">Back to the index</a>
44    
45     <p><br>
46     <h2>Technical details</h2>
47    
48     <p>
49     This page describes some of the internals of GXemul.
50    
51     <p>
52 dpavlin 6 <font color="#e00000"><b>NOTE: This page is probably not
53     very up-to-date by now.</b></font>
54    
55     <p>
56 dpavlin 2 <ul>
57     <li><a href="#overview">Overview</a>
58     <li><a href="#speed">Speed</a>
59     <li><a href="#net">Networking</a>
60     <li><a href="#devices">Emulation of hardware devices</a>
61     <li><a href="#regtest">Regression tests</a>
62     </ul>
63    
64    
65    
66    
67     <p><br>
68     <a name="overview"></a>
69     <h3>Overview</h3>
70    
71     In simple terms, GXemul is just a simple fetch-and-execute
72     loop; an instruction is fetched from memory, and executed.
73    
74     <p>
75     In reality, a lot of things need to be handled. Before each instruction is
76     executed, the emulator checks to see if any interrupts are asserted which
77     are not masked away. If so, then an INT exception is generated. Exceptions
78     cause the program counter to be set to a specific value, and some of the
79     system coprocessor's registers to be set to values signifying what kind of
80     exception it was (an interrupt exception in this case).
81    
82     <p>
83     Reading instructions from memory is done through a TLB, a translation
84     lookaside buffer. The TLB on MIPS is software controlled, which means that
85     the program running inside the emulator (for example an operating system
86     kernel) has to take care of manually updating the TLB. Some memory
87     addresses are translated into physical addresses directly, some are
88     translated into valid physical addresses via the TLB, and some memory
89     references are not valid. Invalid memory references cause exceptions.
90    
91     <p>
92     After an instruction has been read from memory, the emulator checks which
93     opcode it contains and executes the instruction. Executing an instruction
94     usually involves reading some register and writing some register, or perhaps a
95     load from memory (or a store to memory). The program counter is increased
96     for every instruction.
97    
98     <p>
99     Some memory references point to physical addresses which are not in the
100     normal RAM address space. They may point to hardware devices. If that is
101     the case, then loads and stores are converted into calls to a device
102     access function. The device access function is then responsible for
103     handling these reads and writes. For example, a graphical framebuffer
104     device may put a pixel on the screen when a value is written to it, or a
105     serial controller device may output a character to stdout when written to.
106    
107    
108    
109    
110     <p><br>
111     <a name="speed"></a>
112     <h3>Speed</h3>
113    
114     There are two modes in which the emulator can run, <b>a</b>) a straight forward
115     loop which fetches one instruction from emulated RAM and executes it
116     (described in the previous section), and <b>b</b>)
117     using dynamic binary translation.
118    
119     <p>
120     Mode <b>a</b> is very slow. On a 2.8 GHz Intel Xeon host the resulting
121     emulated machine is rougly equal to a 7 MHz R3000 (or a 3.5 MHz R4000).
122     The actual performance varies a lot, maybe between 5 and 10 million
123     instructions per second, depending on workload.
124    
125     <p>
126     Mode <b>b</b> ("bintrans") is still to be considered experimental, but
127     gives higher performance than mode <b>a</b>. It translates MIPS machine
128     code into machine code that can be executed on the host machine
129     on-the-fly. The translation itself obviously takes some time, but this is
130     usually made up for by the fact that the translated code chunks are
131     executed multiple times.
132 dpavlin 6 To run the emulator with binary translation enabled, just add
133     <tt><b>-b</b></tt> to the command line.
134 dpavlin 2
135     <p>
136     Only small pieces of MIPS machine code are translated, usually the size of
137     a function, or less. There is no "intermediate representation" code, so
138     all translations are done directly from MIPS to host machine code.
139    
140     <p>
141     The default bintrans cache size is 16 MB, but you can change this by adding
142 dpavlin 6 <tt>-DDEFAULT_BINTRANS_SIZE_IN_MB=<i>xx</i></tt> to your CFLAGS environment
143     variable before running the configure script, or by using the
144     <tt>bintrans_size()</tt> configuration file option when running the emulator.
145 dpavlin 2
146     <p>
147     By default, an emulated OS running under DECstation emulation which listens to
148     interrupts from the mc146818 clock will get interrupts that are close to the
149     host's clock. That is, if the emulated OS says it wants 100 interrupts per
150     second, it will get approximately 100 interrupts per real second.
151    
152     <p>
153 dpavlin 6 There is however a <tt><b>-I</b></tt> option, which sets the number of
154     emulated cycles per seconds to a fixed value. Let's say you wish to make the
155     emulated OS think it is running on a 40 MHz DECstation, and not a 7 MHz one,
156     then you can add <tt><b>-I 40000000</b></tt> to the command line. This will not
157     make the emulation faster, of course. It might even make it seem slower; for
158     example, if NetBSD/pmax waits 2 seconds for SCSI devices to settle during
159     bootup, those 2 seconds will take 2*40000000 cycles (which will take more
160     time than 2*7000000).
161 dpavlin 2
162     <p>
163 dpavlin 6 The <b><tt>-I</tt></b> option is also necessary if you want to run
164     deterministic experiments, if a mc146818 (or similar) device is present.
165 dpavlin 2
166     <p>
167     Some emulators make claims such as "x times slowdown," but in the case of
168     GXemul, the host is often not a MIPS-based machine, and hence comparing
169     one MIPS instruction to a host instruction doesn't work. Performance depends on
170     a lot of factors, including (but not limited to) host architecture, host speed,
171     which compiler and compiler flags were used to build GXemul, what the
172     workload is, and so on. For example, if an emulated operating system tries
173     to read a block from disk, from its point of view the read was instantaneous
174     (no waiting). So 1 MIPS in an emulated OS might have taken more than one
175     million instructions on a real machine. Because of this, imho it is best
176     to measure performance as the actual (real-world) time it takes to perform
177     a task with the emulator.
178    
179    
180    
181    
182     <p><br>
183     <a name="net"></a>
184     <h3>Networking</h3>
185    
186     Running an entire operating system under emulation is very interesting in
187     itself, but for several reasons, running a modern OS without access to
188     TCP/IP networking is a bit akward. Hence, I feel the need to implement TCP/IP
189     (networking) support in the emulator.
190    
191     <p>
192     As far as I have understood it, there seems to be two different ways to go:
193    
194     <ol>
195     <li>Forward ethernet packets from the emulated ethernet controller to
196     the host machine's ethernet controller, and capture incoming
197     packets on the host's controller, giving them back to the
198     emulated OS. Characteristics are:
199     <ul>
200     <li>Requires <i>direct</i> access to the host's NIC, which
201     means on most platforms that the emulator cannot be
202     run as a normal user!
203     <li>Reduced portability, as not every host operating system
204     uses the same programming interface for dealing with
205     hardware ethernet controllers directly.
206     <li>When run on a switched network, it might be problematic to
207     connect from the emulated OS to the OS running on the
208     host, as packets sent out on the host's NIC are not
209     received by itself. (?)
210 dpavlin 6 <li>All specific networking protocols will be handled by the
211     physical network.
212 dpavlin 2 </ul>
213     <p>
214     or
215     <p>
216     <li>Whenever the emulated ethernet controller wishes to send a packet,
217     the emulator looks at the packet and creates a response. Packets
218     that can have an immediate response never go outside the emulator,
219     other packet types have to be converted into suitable other
220     connection types (UDP, TCP, etc). Characteristics:
221     <ul>
222     <li>Each packet type sent out on the emulated NIC must be handled.
223     This means that I have to do a lot of coding.
224     (I like this, because it gives me an opportunity to
225     learn about networking protocols.)
226     <li>By not relying on access to the host's NIC directly,
227     portability is maintained. (It would be sad if the networking
228     portion of a portable emulator isn't as portable as the
229     rest of the emulator.)
230     <li>The emulator can be run as a normal user process, does
231     not require root privilegies.
232     <li>Connecting from the emulated OS to the host's OS should
233     not be problematic.
234     <li>The emulated OS will experience the network just as a single
235     machine behind a NAT gateway/firewall would. The emulated
236     OS is thus automatically protected from the outside world.
237     </ul>
238     </ol>
239    
240 dpavlin 6 <p>
241     Some emulators/simulators use the first approach, while others use the
242     second. I think that SIMH and QEMU are examples of emulators using the
243     first and second approach, respectively.
244 dpavlin 2
245     <p>
246     Since I have choosen the second kind of implementation, I have to write
247     support explicitly for any kind of network protocol that should be
248     supported. As of 2004-07-09, the following has been implemented and seems
249     to work under at least NetBSD/pmax and OpenBSD/pmax under DECstation 5000/200
250     emulation (-E dec -e 3max):
251    
252     <p>
253     <ul>
254     <li>ARP requests sent out from the emulated NIC are interpreted,
255     and converted to ARP responses. (This is used by the emulated OS
256     to find out the MAC address of the gateway.)
257     <li>ICMP echo requests (that is the kind of packet produced by the
258 dpavlin 6 <b><tt>ping</tt></b> program) are interpreted and converted to ICMP echo
259 dpavlin 2 replies, <i>regardless of the IP address</i>. This means that
260     running ping from within the emulated OS will <i>always</i>
261     receive a response. The ping packets never leave the emulated
262     environment.
263     <li>UDP packets are interpreted and passed along to the outside world.
264     If the emulator receives an UDP packet from the outside world, it
265     is converted into an UDP packet for the emulated OS. (This is not
266     implemented very well yet, but seems to be enough for nameserver
267     lookups, tftp file transfers, and NFS mounts using UDP.)
268     <li>TCP packets are interpreted one at a time, similar to how UDP
269     packets are handled (but more state is kept for each connection).
270     <font color="#ff0000">NOTE: Much of the TCP handling code is very
271     ugly and hardcoded.</font>
272 dpavlin 6 <!--
273 dpavlin 2 <li>RARP is not implemented yet. (I haven't needed it so far.)
274 dpavlin 6 -->
275 dpavlin 2 </ul>
276    
277 dpavlin 6 <p>
278 dpavlin 2 The gateway machine, which is the only "other" machine that the emulated
279     OS sees on its emulated network, works as a NAT-style firewall/gateway. It
280 dpavlin 6 usually has a fixed IPv4 address of <tt>10.0.0.254</tt>. An OS running in
281     the emulator would usually have an address of the form <tt>10.x.x.x</tt>;
282     a typical choice would be <tt>10.0.0.1</tt>.
283 dpavlin 2
284     <p>
285 dpavlin 6 Inside emulated NetBSD/pmax or OpenBSD/pmax, running the following
286     commands should configure the emulated NIC:
287 dpavlin 2 <pre>
288     # <b>ifconfig le0 10.0.0.1</b>
289     # <b>route add default 10.0.0.254</b>
290     add net default: gateway 10.0.0.254
291     </pre>
292    
293 dpavlin 6 <p>
294 dpavlin 2 If you want nameserver lookups to work, you need a valid /etc/resolv.conf
295     as well:
296     <pre>
297     # <b>echo nameserver 129.16.1.3 > /etc/resolv.conf</b>
298     </pre>
299 dpavlin 6 (But replace <tt>129.16.1.3</tt> with the actual real-world IP address of
300     your nearest nameserver.)
301    
302 dpavlin 2 <p>
303     Now, host lookups should work:
304     <pre>
305     # <b>host -a www.netbsd.org</b>
306     Trying null domain
307     rcode = 0 (Success), ancount=2
308     The following answer is not authoritative:
309     The following answer is not verified as authentic by the server:
310     www.netbsd.org 86400 IN AAAA 2001:4f8:4:7:290:27ff:feab:19a7
311     www.netbsd.org 86400 IN A 204.152.184.116
312     For authoritative answers, see:
313     netbsd.org 83627 IN NS uucp-gw-2.pa.dec.com
314     netbsd.org 83627 IN NS ns.netbsd.org
315     netbsd.org 83627 IN NS adns1.berkeley.edu
316     netbsd.org 83627 IN NS adns2.berkeley.edu
317     netbsd.org 83627 IN NS uucp-gw-1.pa.dec.com
318     Additional information:
319     ns.netbsd.org 83627 IN A 204.152.184.164
320     uucp-gw-1.pa.dec.com 172799 IN A 204.123.2.18
321     uucp-gw-2.pa.dec.com 172799 IN A 204.123.2.19
322     </pre>
323    
324 dpavlin 6 <p>
325     At this point, UDP and TCP should (mostly) work.
326 dpavlin 2
327 dpavlin 6 <p>
328     Here is an example of how to configure a server machine and an emulated
329     client machine for sharing files via NFS:
330 dpavlin 2
331 dpavlin 6 <p>
332     (This is very useful if you want to share entire directory trees
333     between the emulated environment and another machine. These instruction
334     will work for FreeBSD, if you are running something else, use your
335     imagination to modify them.)
336 dpavlin 2
337     <p>
338     <ul>
339     <li>On the server, add a line to your /etc/exports file, exporting
340     the files you wish to use in the emulator:<pre>
341     <b>/tftpboot -mapall=nobody -ro 123.11.22.33</b>
342     </pre>
343     where 123.11.22.33 is the IP address of the machine running the
344     emulator process, as seen from the outside world.
345     <p>
346     <li>Then start up the programs needed to serve NFS via UDP. Note the
347     -n argument to mountd. This is needed to tell mountd to accept
348     connections from unprivileged ports (because the emulator does
349     not need to run as root).<pre>
350     # <b>portmap</b>
351     # <b>nfsd -u</b> &lt;--- u for UDP
352     # <b>mountd -n</b>
353     </pre>
354     <li>In the guest OS in the emulator, once you have ethernet and IPv4
355     configured so that you can use UDP, mounting the filesystem
356     should now be possible: (this example is for NetBSD/pmax
357     or OpenBSD/pmax)<pre>
358     # <b>mount -o ro,-r=1024,-w=1024,-U,-3 my.server.com:/tftpboot /mnt</b>
359     or
360     # <b>mount my.server.com:/tftpboot /mnt</b>
361     </pre>
362     If you don't supply the read and write sizes, there is a risk
363     that the default values are too large. The emulator currently
364     does not handle fragmentation/defragmentation of <i>outgoing</i>
365     packets, so going above the ethernet frame size (1518) is a very
366     bad idea. Incoming packets (reading from nfs) should work, though,
367     for example during an NFS install.
368     </ul>
369    
370     The example above uses read-only mounts. That is enough for things like
371     letting NetBSD/pmax or OpenBSD/pmax install via NFS, without the need for
372     a CDROM ISO image. You can use a read-write mount if you wish to share
373     files in both directions, but then you should be aware of the
374     fragmentation issue mentioned above.
375    
376    
377    
378    
379    
380     <p><br>
381     <a name="devices"></a>
382     <h3>Emulation of hardware devices</h3>
383    
384     Each file in the device/ directory is responsible for one hardware device.
385     These are used from src/machine.c, when initializing which hardware a
386     particular machine model will be using, or when adding devices to a
387     machine using the <b>device()</b> command in configuration files.
388    
389     <p>
390     <font color="#ff0000">NOTE: 2005-02-26: I'm currently rewriting the
391     device registry subsystem.</font>
392    
393     <p>
394     (I'll be using the name 'foo' as the name of the device in all these
395     examples. This is pseudo code, it might need some modification to
396     actually compile and run.)
397    
398     <p>
399     Each device should have the following:
400    
401     <p>
402     <ul>
403     <li>A devinit function in dev_foo.c. It would typically look
404     something like this:
405     <pre>
406     /*
407     * devinit_foo():
408     */
409     int devinit_foo(struct devinit *devinit)
410     {
411     struct foo_data *d = malloc(sizeof(struct foo_data));
412    
413     if (d == NULL) {
414     fprintf(stderr, "out of memory\n");
415     exit(1);
416     }
417     memset(d, 0, sizeof(struct foon_data));
418    
419     /*
420     * Set up stuff here, for example fill d with useful
421     * data. devinit contains settings like address, irq_nr,
422     * and other things.
423     *
424     * ...
425     */
426    
427     memory_device_register(devinit->machine->memory, devinit->name,
428     devinit->addr, DEV_FOO_LENGTH,
429     dev_foo_access, (void *)d, MEM_DEFAULT, NULL);
430    
431     /* This should only be here if the device
432     has a tick function: */
433     machine_add_tickfunction(machine, dev_foo_tick, d,
434     FOO_TICKSHIFT);
435    
436     /* Return 1 if the device was successfully added. */
437     return 1;
438     }
439     </pre><br>
440    
441     <li>At the top of dev_foo.c, the foo_data struct should be defined.
442     <pre>
443     struct foo_data {
444     int irq_nr;
445     /* ... */
446     }
447     </pre><br>
448    
449     <li>If foo has a tick function (that is, something that needs to be
450     run at regular intervals) then FOO_TICKSHIFT and a tick function
451     need to be defined as well:
452     <pre>
453     #define FOO_TICKSHIFT 10
454    
455     void dev_foo_tick(struct cpu *cpu, void *extra)
456     {
457     struct foo_data *d = (struct foo_data *) extra;
458    
459     if (.....)
460     cpu_interrupt(cpu, d->irq_nr);
461     else
462     cpu_interrupt_ack(cpu, d->irq_nr);
463     }
464     </pre><br>
465    
466     <li>And last but not least, the device should have an access function.
467     The access function is called whenever there is a load or store
468     to an address which is in the device' memory mapped region.
469     <pre>
470     int dev_foo_access(struct cpu *cpu, struct memory *mem,
471     uint64_t relative_addr, unsigned char *data, size_t len,
472     int writeflag, void *extra)
473     {
474     struct foo_data *d = extra;
475     uint64_t idata = 0, odata = 0;
476    
477     idata = memory_readmax64(cpu, data, len);
478     switch (relative_addr) {
479     /* .... */
480     }
481    
482     if (writeflag == MEM_READ)
483     memory_writemax64(cpu, data, len, odata);
484    
485     /* Perhaps interrupts need to be asserted or
486     deasserted: */
487     dev_foo_tick(cpu, extra);
488    
489     /* Return successfully. */
490     return 1;
491     }
492     </pre><br>
493     </ul>
494    
495     <p>
496 dpavlin 6 The return value of the access function has until 2004-07-02 been a
497 dpavlin 2 true/false value; 1 for success, or 0 for device access failure. A device
498     access failure (on MIPS) will result in a DBE exception.
499    
500     <p>
501     Some devices are converted to support arbitrary memory latency
502     values. The return value is the number of cycles that the read or
503     write access took. A value of 1 means one cycle, a value of 10 means 10
504     cycles. Negative values are used for device access failures, and the
505     absolute value of the value is then the number of cycles; a value of -5
506     means that the access failed, and took 5 cycles.
507    
508     <p>
509     To be compatible with pre-20040702 devices, a return value of 0 is treated
510 dpavlin 6 by the caller (in <tt>src/memory_rw.c</tt>) as a value of -1.
511 dpavlin 2
512    
513    
514    
515    
516     <p><br>
517     <a name="regtest"></a>
518     <h3>Regression tests</h3>
519    
520     In order to make sure that the emulator actually works like it is supposed
521     to, it must be tested. For this purpose, there is a simple regression
522 dpavlin 6 testing framework in the <tt>tests/</tt> directory.
523 dpavlin 2
524     <p>
525     <i>NOTE: The regression testing framework is basically just a skeleton so far.
526     Regression tests are very good to have. However, the fact that complete
527     operating systems can run in the emulator indicate that the emulation is
528     probably not too incorrect. This makes it less of a priority to write
529     regression tests.</i>
530    
531     <p>
532 dpavlin 6 To run all the regression tests, type <tt>make regtest</tt>. Each assembly
533     language file matching the pattern <tt>test_*.S</tt> will be compiled and
534 dpavlin 2 linked into a 64-bit MIPS ELF (using a gcc cross compiler), and run in the
535     emulator. If everything goes well, you should see something like this:
536    
537     <pre>
538     $ make regtest
539     cd tests; make run_tests; cd ..
540     gcc33 -Wall -fomit-frame-pointer -fmove-all-movables -fpeephole -O2
541     -mcpu=ev5 -I/usr/X11R6/include -lm -L/usr/X11R6/lib -lX11 do_tests.c
542     -o do_tests
543     do_tests.c: In function `main':
544     do_tests.c:173: warning: unused variable `s'
545     /var/tmp//ccFOupvD.o: In function `do_tests':
546     /var/tmp//ccFOupvD.o(.text+0x3a8): warning: tmpnam() possibly used
547     unsafely; consider using mkstemp()
548     mips64-unknown-elf-gcc -g -O3 -fno-builtin -fschedule-insns -mips64
549     -mabi=64 test_common.c -c -o test_common.o
550     ./do_tests "mips64-unknown-elf-gcc -g -O3 -fno-builtin -fschedule-insns
551     -mips64 -mabi=64" "mips64-unknown-elf-as -mabi=64 -mips64"
552     "mips64-unknown-elf-ld -Ttext 0xa800000000030000 -e main
553     --oformat=elf64-bigmips" "../gxemul"
554    
555     Starting tests:
556     test_addu.S (-a)
557     test_addu.S (-a -b)
558     test_clo_clz.S (-a)
559     test_clo_clz.S (-a -b)
560     ..
561     test_unaligned.S (-a)
562     test_unaligned.S (-a -b)
563    
564     Done. (12 tests done)
565     PASS: 12
566     FAIL: 0
567    
568     ----------------
569    
570     All tests OK
571    
572     ----------------
573     </pre>
574    
575     <p>
576 dpavlin 6 Each test writes output to stdout, and there is a <tt>test_*.good</tt> for
577     each <tt>.S</tt> file which contains the wanted output. If the actual
578     output matches the <tt>.good</tt> file, then the test passes, otherwise it
579     fails.
580 dpavlin 2
581     <p>
582 dpavlin 6 Read <tt>tests/README</tt> for more information.
583 dpavlin 2
584    
585    
586    
587     </body>
588     </html>

  ViewVC Help
Powered by ViewVC 1.1.26