/[gxemul]/trunk/src/cpu_mips.c
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/src/cpu_mips.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations)
Mon Oct 8 16:17:48 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 120225 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.676 2005/04/07 15:14:55 debug Exp $

Changelog for GXemul:
---------------------

20030829	Skeleton. ELF stuff. Some instructions.
20030830	Simple test programs using +-*/^|&%, function calls,
		loops, and stuff like that work.
20030903	Adding more instructions, fixing some bugs.
20030907	Making adding of memory mapped devices easier, although
		the framework isn't built for speed.
		Adding a -q switch to turn of debug output.
20030911	Trying to fix some bugs. Minor changes. Some COP0
		registers are now meaningful.
20030919	Making APs (non-bootstrap cpus) available via a simple
		'mp' device. Implementing ll/lld and sc/scd (for atomic
		memory updates, needed by MP operating systems).
20030923	Minor updates: more instructions (divu, mulu, lwu,
		perhaps some more), and opcode usage statistics.
20030924	If the next instruction is nullified (for 'branch
		likely' type of instructions), counters for delays etc
		are now decreased as they should.
		Adding some comments.
		Adding instructions: movz, movn.
		Adding a simple mandelbrot test to mipstest.c.
20030925	Adding instructions: bltzl, bgezl, lh, lhu, sh, mfc*,
		mtc*.
		Adding a dummy instructions: sync, cache.
		Adding minimal DECstation PROM functionality: printf()
		and getsysid() callback functions.
		Beginning work on address translation.
20030927	Adding some more cop0 functionality (tlb stuff).
		Adding mc146818 real-time clock. (Skeleton stuff.)
20030928	Adding a dc7085 serial console device (dummy, but enough
		to output chars to the screen). NetBSD uses this for
		the MIPSMATE 5100.
20030929	Working on the TLB stuff.
		Adding instructions: srlv, tlbwr, tlbr, tlbp, eret.
20030930	Trying to find a bug which causes NetBSD to bug out, but
		it is really hard.
		Adding some a.out support (for loading an old
		OpenBSD 2.8/pmax kernel image).
		Adding instructions: lwc*, ldc*, swc1 and swc3.
		Beginning to add special code to handle the differences
		between R4000 (the default emulation) and R2000/R3000.
20031001	Symbol listings produced by 'nm -S' can be used to
		show symbolic names for addresses. (-S)
20031002	Fixing the i/d fake cache for R2000/R3000. It's still
		just an ugly hack, though.
		Fixing minor bugs to make the 3100 emulation use the
		dc device (serial console) correctly. So far, 5100 and
		3100 are the only ones that get far enough to print
		stuff, when booting NetBSD.
20031004	Adding skeleton Cobalt machine emulation (-E).
		Adding a dummy ns16550 serial controller, used by the
		Cobalt machine emulation.
20031006	Adding unaligned load/store instructions (lwl, lwr,
		ldl, ldr, swl, swr, sdl, sdr), although they are not
		tested yet.
		Fixed a "data modified on freelist" bug when running
		NetBSD/cobalt: setting the top bit of the index register
		when a tlbp fails (as the R4000 manual says) isn't
		sufficient, I had to clear the low bits as well.
		Adding break and syscall instructions, but they are not
		tested yet.
		Adding a 'gt' device, faking a PCI bus, for the Cobalt
		emulation.
20031008	Adding initial support for HPCmips (-F), a framebuffer
		device using X11. NetBSD/hpcmips can output pixels to
		the framebuffer, but that's about it.
20031009	Fixing the NetBSD/pmax bug: the "0/tftp/netbsd" style
		bootstring was only passed correctly in the bootinfo
		block, it needs to be passed as argv[0] as well.
		Adding instructions: mtlo, mthi.
		Rearrangning the source tree layout.
		Adding console input functionality. The NetBSD/cobalt
		kernel's ddb can now be interacted with.
20031010	Adding experimental (semi-useless) -t option, to show
		a function call tree while a program runs.
		Linux/cobalt now prints a few messages, but then hangs
		at "Calibrating delay loop..." unless an ugly hack is
		used (setting a word of memory at 0x801e472c to non-zero).
20031013	Adding a framebuffer device used in DECstation 3100;
		VFB01 for mono is implemented so far, not yet the
		VFB02 (color) variant.  Rewriting the framebuffer
		device so that it is usable by both HPCmips and DECstation
		emulation.
20031014	Minor fixes. Everything should compile and run ok
		both with and without X11.
20031015	Adding support for ECOFF binary images; text, data,
		and symbols are loaded. (Playing around with ultrixboot
		and ultrix kernels.)
20031016	The DECstation argv,argc stuff must be at 0xa0000000,
		not 0x80000000, or Ultrix kernels complain.
		Adding R2000/R3000 'rfe' instruction.
		Implementing more R2K/R3K tlb specific stuff, so that
		NetBSD boots and uses the tlb correctly, but much of
		it is ugly. (Needs to be separated in a cleaner way.)
		ECOFF symbols sizes are now calculated, so that offsets
		within symbols are usable.
20031017	DECstation bootstrings now automatically include the
		correct name of the kernel that is booting.
		Ultrix boots a bit.
20031018	ELF symbols are now read automatically from the binary.
		-t trace looks a bit better (string arguments are shown).
		Trying to get initial R5900 stuff working (the 128-bit
		CPU used in Playstation 2).
		Fixing a minor bug to make the VFB02 (color framebuffer)
		device work better, but it is still just 256 grayscales,
		not real color. Ultrix can now use the framebuffer (it
		calls it PMAX-CFB).
		A machine can now consist of CPUs of different types.
		Adding instructions: daddi, mov_xxx, mult_xx. The xxx
		instructions are not documented MIPS64 instructions,
		but NetBSD/playstation2 uses them. Perhaps VR5432
		instructions?
		Adding sign-extension to 32-bit mult.
		Adding Playstation 2 devices: dmac (DMA controller),
		gs (Graphic something?), and gif (graphics something
		else, which has access to the PS2's framebuffer).
		NetBSD/playstation2 works a bit, and prints a few
		bootup messages.
20031020	The cpu_type field of the cpu struct now contains
		usable values in a much better form than before. This
		simplifies adding of new CPU types.
20031021	Fixing an interrupt related bug: pc_last was used, but
		for interrupts this was incorrect. Fixed now.
		Fixing a load/store related bug: if a load into a
		register was aborted due to an exception, the register
		was still modified.
		The mc146818 rtc now reads its time from the system's
		time() function.
		Fixing another exception bug: if loading an instruction
		caused an exception, something bogus happened as the
		emulator tried to execute the instruction anyway. This
		has been fixed now.
20031023	Adding a quick hack which skips "while (reg --) ;"
		kind of loops.
		NetBSD/pmax suddenly reached userland (!), but only
		once and attempts to repeat it have failed. I believe
		it is problems with my interrupt handling system.
20031024	Adding 8-bit color palette support to the framebuffer.
		Connecting the pmax vdac device to the framebuffer's
		rgb palette.
		Fixing a bug in the dc device, so that console input
		is possible; interaction with NetBSD/pmax's built-in
		kernel debugger works now.
		Symbol sizes for file formats where symbol size isn't
		included are now calculated regardless of file format.
		Physical memory space can now be smaller than 64 bits,
		improving emulation speed a bit.
		Doing other minor performance enhancements by moving
		around some statements in critical parts of the code.
20031025	Minor changes to the dc device.
20031026	Adding support for reading symbols directly from
		a.out files. (Works with OpenBSD/pmax binaries.)
		Hardware devices may now register "tick functions" at
		specific cycle intervals in a generic fashion.
		All four channels of the dc serial controller device
		should now work; playing around with keyboard scan
		code generation when using the DECstation framebuffer.
		Making various (speed) improvements to the framebuffer
		device.
20031027	Playing around with the sii SCSI controller.
20031028	Minor fixes.
		Adding an SGI emulation mode (-G), and some ARCBIOS
		stuff, which SGIs seem to use.
		Adding getbitmap() to the DEC prom emulation layer,
		so some more -D x models become more usable.
		Adding a dummy 'ssc' serial console device for
		DECsystem 5400 emulation.
		Playing around with TURBOchannel stuff.
20031030	Minor fixes.
		Adding the sub instruction. (Not tested yet?)
		Sign-extending the results of multu, addi,addiu,
		add,addu,sub,subu,mfcZ.
		Adding a colorplanemask device for DECstation 3100.
		Fixed the NetBSD/pmax bug: I had forgotten to reset
		asid_match to 0 between tlb entry checks. :-)  Now
		userland runs nicely...
20031031	Fixing more bugs:  unaligned load/store could fail
		because of an exception, but registers could be "half
		updated". This has been fixed now.  (As a result,
		NetBSD/pmax can now run with any of r2000,r3000,r4000,
		r4400, or r5000.)
		Adding some R5K and R10000 stuff.  (Note: R5K is NOT
		R5000. Weird.)
		Adding dummy serial console (scc) for MAXINE.
		MAXINE also works with framebuffer, but there is no
		color palette yet (only black and white output).
20031101	Moving code chunks around to increase performance by
		a few percent.
		The opcode statistics option (-s) now shows opcode
		names, and not just numbers. :-)
		Fixing the bug which caused NetBSD/pmax to refuse
		input in serial console mode, but not in keyboard/
		framebuffer mode: the osconsole environment variable
		wasn't set correctly.
		Adding DEC PROM getchar() call.
		The transmitter scanner of the dc device now scans
		all four channels at once, for each tick, so serial
		output is (approximately) 4 times faster.
20031103	Adding a dummy BT459 vdac device, which does nothing
		but allows a PMAG-BA turbochannel graphics card to be
		used as framebuffer.
		Several DECstation machines (-D 2, 3, and 4) can now
		use TURBOchannel option card framebuffers as console,
		for output. (Keyboard input is still not implemented
		for those models.)  Only PMAG-AA (1280x1024x8) and
		PMAG-BA (1024x864x8), both using BT459 vdac, have
		been tested so far.
		Modifying the X11 routines so that several framebuffer
		windows now can be used simultaneously (if several
		graphics option cards are to be emulated concurrently).
20031104	DEC MIPSMATE 5100 (KN230) interrupts are shared
		between devices. I've added an ugly hack to allow
		that to work, which makes it possible to boot NetBSD
		into userland with serial console.
20031106	Removing the -S (symbol) option, as symbol files can
		now be given in any order together with other file
		names to be loaded.
		cookin tipped me about using (int64_t) (int32_t)
		casts instead of manually sign-extending values.
		Casting sometimes increases performance, sometimes
		decreases. It's tricky.
		Importing mips64emul into CVS.
20031107	Adding a generic ARC emulation mode.
		Increasing performance of the framebuffer by not
		updating it (or the XImage) if a write to the
		framebuffer contains exactly what is already in it.
		(This improves scrolling speed and initialization.)
		Adding initial MIPS16 support.
		Adding initial disk image support (-d command line
		option), but this will not be used until I get some
		kind of SCSI-controller emulation working.
20031108	Adding the first MIPS16 instructions: "move y,X",
		"ld y,D(x)", and "daddiu S,K" (but the last one
		doesn't work yet).
		Fixing the console environment variable for
		Enough of the 'asc' controller is now implemented
		to let NetBSD get past scsi disk detection when
		no disk images are used.
		DECstation machine type 2; both serial console and
		graphical console work now.
		Other X-windows bit-depths than 24 bits work now,
		but colors are still not correct in non-24 bit modes.
		Keypresses in X framebuffer windows are now
		translated into console keypresses. (Normal keys, but
		not cursor keys or other special keys.)
20031111	Adding support for X11 using non-24-bit output.
20031120	Adding X11 mouse event to emulated mouse event
		translation, but it's not tested yet.
		Trying to get more of the SCSI controller emulation
		to work.
20031124	Raw binaries can now be loaded into memory.
20031204	Adding srec binary support.
20031220	Adding some super-ugly arcbios emulation code.
		Making some progress on the SGI and ARC machine
		emulations.
20031222	SGI and ARC progress. Multiple CPUs are now added to
		the arcbios component tree (although NetBSD cannot
		actually use more than one).
20031228	Adding 'crime' and 'macepci' fake devices for SGI
		emulation.
		Finally implementing the cop0 'compare' register.
		Improvements to the ns16550 device, but it is still
		incomplete.
		SGI userland is now reached, but interaction is broken
		(due to the buggy ns16550).
20031229	Adding some more instructions: teq, dsllv
		Adding a Nintendo 64 emulation mode (skeleton).
		Adding R4300 and R12000 to the cpu list.
20031230	Adding bltzal, bltzall, bgezal, bgezall (not really
		tested yet).
		Fixing the 16550 serial controller device (by not
		supporting fifo, so in fact it emulates a 16450
		instead).  This causes NetBSD/sgimips to run nicely
		into userland, sysinst, and so on.
		Some ARC/RD94 interrupts seem to work ok now, but
		i/o interrupts are still not correctly implemented.
		NetBSD/arc userland is reached and can be interacted
		with, but there's no sysinst (?).
20040103	Trying to get some Irix stuff to work, but it's hard.
		Fixing some Cobalt/linux problems.
20040104	Adding a dummy 8250 device, so that Linux/sgimips can output
		console messages.
		Adding dmultu. (The same as dmult, so I'm not sure it's correct.
		Perhaps dmultu is correct and dmult is wrong...)
		Fixing a bug in unaligned load/stores of 64-bit values (a cast
		was needed).
		Linux/sgimips in 64-bit works a bit more than before.
		Adding simple (polled) input functionality to dev_zs.
		Making some progress on SGI-IP22 (IP32 still works best,
		though).
		Fixing the mc146818 clock device in ARC/NEC and SGI emulation
		modes, the year field was not correct.
		Adding a fake 'pref' instruction (lwc3).
20040106	Separating out memory.h from misc.h.
		Refactoring of a lot of small code fragments.
		The PCI bus device is now shared between Cobalt, SGI, and ARC.
		Support for RAM mirroring (dev_ram.c, not really tested yet).
		Ugly hack to select the largest of ELF string symbol tables,
		if there are more than one.
		Memory hole fix for ARCBIOS, and a fix for very large (>= 4GB)
		amounts of emulated RAM.
		TGA (DEC 21030) PCI graphics device. NetBSD/arc can boot with
		this card and use it as a framebuffer console.
20040107	Adding a fix (partly incorrect) to daddi, to allow Linux/sgimips
		to boot in 64-bit mode.
20040108	Fixing a sll/nop bug (rd==0 for nop, not sa==0 as before).
20040109	Trying to get an SGI-IP32 PROM image to boot.
20040110	Faking R10000 cache things.
		The PROM image boots, although it takes almost forever for it
		to realize that there is no keyboard.
		The 'gbe' SGI-IP32 graphics device works enough to display the
		Linux framebuffer penguin in the upper left corner :-)
20040111	-p and -P addresses can now be given as symbol names, not just
		numeric values.
		Experimenting with adding a PCIIDE (dev_wdc) controller to the
		Cobalt emulation.
20040120	Adding src/bintrans.c. No code yet, but this is a place for
		ideas to be written down.
		Increasing performance a little bit by inlining the check for
		interrupts (which occurs for every instruction).
20040124	Experimenting with pure userland (syscall) emulation.
20040127	Fixes for compiling under Solaris.
20040206	Some bintrans experiments.
20040209	Adding some simple Ultrix userland emulation syscalls.
20040211	Adding decprom_dump_txt_to_bin.c to the experiments/ dir.
		Adding a section to doc/ on how to use DECstation PROM dumps.
		Adding a hello world example to doc/ as well.
20040218	TURBOchannel slots that are empty now return a DBE exception,
		so that Ultrix and DECstation PROMs don't complain about
		broken TURBOchannel ROMs.
		Working some more on the machine-dependant interrupt stuff.
20040219	Trying out some Linux/DECstation kernels (semi-successfully).
20040222	YES! I finally found the bug that caused Linux/SGI-IP32 to only
		work on Alpha, not on 32-bit machines.  It was a shift left,
		probably done using 6 bits on alpha, 5 bits on 32-bit machines.
20040223	Some minimal DEC KN5800 progress; Ultrix prints some boot
		messages, detects 16 XMI R3000 cpus, and get a NULL panic.
		It's all fake, though, the CPUs don't actually work.
		Still, better than nothing :-)
20040225	An Ultrix OSF1 kernel with a ramdisk now boots :-)  (It was
		a problem with ultrixboot not giving the same arguments as
		NetBSD's boot program.)
20040225(later)	Fixing a bug in the DECstation dc serial device; digits 0-9
		were translated to numeric keypad 0-9, not the normal 0-9.
		(This caused Ultrix to print escape sequences instead of
		digits.)
20040226	Some progress on machine-dependant interrupt delivery
		for -D7 (Maxine) and -D4, and some more 'scc' serial
		controller featuers are implemented (but no interrupts/
		dma/keyboard/mouse stuff yet).
20040228	Progress on the scc controller; -D4 works in both serial
		console mode and with keyboard (graphical console), but no
		mouse yet.
20040301	SGI mace interrupts are now done using the new machine-
		independant interrupt system.
20040303	Fixing an R5900 bug; the lowest 6 bits have special meaning
		for coprocessor functions, not just 5 bits as on non-R5900
		CPUs. (This fixes a bug which caused NetBSD to crash.)
20040304	Adding enough (fake) DMA capabilities to the ioasic device
		to allow Ultrix to print boot messages in the -D3, -D4,
		and -D7 modes, and also print graphical console messages
		in -D4 and -D7 modes.
		-D11 (DEC5500) polled getchar added (to the 'ssc' device).
		Adding the 'madd' instruction (including R5900 weird stuff).
20040304(later)	Playstation 2's GIF can now copy 640x16 pixel chunks, allowing
		NetBSD to scroll up the framebuffer.  The cursor also works
		better now.
		Playstation 2 bootinfo RTC data should now be passed correctly
		to the running kernel.
		DECstation rtc year should be either 72 or 73, anything else
		will cause Ultrix to give a warning about invalid year.
20040306	Combining playstation2's dmac, interrupt, and timer devices
		into one (ps2_stuff).
		Adding some R5900 instructions: mfsa, mtsa, pmfhi, pmflo, por,
		lq, and sq.  (Most of them are just guesses, though.)
		Implementing my own XImage putpixel routine, which can be
		inlined... significantly faster than normal XPutPixel. :-)
20040307	Implementing the basic functionality of a "PMAG-CA" pixelstamp
		accellerated framebuffer device. Works with NetBSD and
		Ultrix, but no cursor or color support.
20040308	PMAG-CA, -DA, and -FA pixelstamps seem to work now.
		Adding a hack to allow a pmax/mach kernel to be loaded (it's
		a COFF file with 0 (!) sections).
		Initial test of bt459 + framebuffer cursor support.
20040309	Fixes/updates of dev_dec5800 and dev_ssc (and dev_decxmi) allow
		a KN5800 Ultrix-OSF1-ramdisk kernel to boot all the way into
		userland and be interacted with.
		The bt459 cursor should now look semi-nice, but it is still
		a bit fake.
20040310	Moving the DEC CCA stuff from src/machine.c into a separate
		device file (devices/dev_deccca.c).
		An ugly hack added to allow some more OSF/1 kernels (almost
		a.out, but without many of the header fields) to load.
20040314	Adding PMAG-JA and PMAG-RO (1280x1024 x 8-bit) TURBOchannel
		graphics devices. They work in Ultrix, but only monochrome
		and no cursor, because there are no ramdacs or such yet.
20040315	Pixelstamp solid fill now supports colors other than just
		zero-fill.
		Adding a (new) regression test skeleton.
20040321	Some really minor updates.
20040323	Fixes to allow SGI-IP20 and IP22 to work a bit better
		(aliased memory), and adding "private" firmware-like vectors
		to arcbios emul. An IP22 Irix kernel gets far enough to
		print an assertion warning (and then double panics). :-)
20040324	Adding a generalization hack to the SCC serial controller
		to work with SGI-IP19 (in addition to DECstations).
		Adding the 'sdc1' instruction.
		Some progress on various SGI emulation modes.
20040325	Minor updates.
20040326	Fixed a 'madd' bug (r5900). NetBSD/playstation2 now reaches
		userland correctly.  And a simple fix which allows NetBSD
		timer interrupts to be triggered; NetBSD uses T_MODE_CMPE
		(compare), while Linux uses _OVFE (overflow).
20040328	Linux on Playstation 2 boots a bit. The Playstation 2
		graphics controller has been extended to work better with
		NetBSD, and to include some Linux support as well.
		Some interrupt handling enhancements on Playstation 2,
		needed for Linux' dma.
		128-bit loads and stores (lq and sq) are allowed, although
		the top half of quadwords are not modified by other
		instructions. (Linux uses lq and sq.)
		Big-endian X Windows servers now display correct rgb color,
		not bgr as before.
20040330	Some minor updates to the documentation.
20040401	Adding a dummy ps2 OHCI device.
20040402	Progress on the asc SCSI controller.
20040406	Hack to allow ./configure, make to work on HP-UX B.11.00
		on HPPA-RISC, gcc 3.3.2. (Does not work with HP's cc.)
		More progress on the asc SCSI controller. Fixing INQUIRY,
		adding READ_CAPACITY, adding READ. Works a bit with NetBSD
		and some (but not all) Ultrix kernels, on DECstation type 2.
		Adding WRITE, SYNCRONIZE_CACHE.
		Mounting disks works in NetBSD :-)  It is a bit buggy,
		though. Or something else is buggy.
20040407	The bug is triggered by gunzip during NetBSD/pmax install.
20040408	Fixing a bug (non-nul-terminated string) which caused X11
		cursors to not display on Solaris.
		Unnecessary X11 redraws are skipped (removes some weird
		delays that existed before), and cursors are redrawn on
		window exposure. (The cursor functionality has been moved
		from dev_fb.c to x11.c.)
20040411	Fixing the DC7085 device so that Ultrix doesn't behave weird
		if both tx and rx interrupts occur at the same time.
		More advancements on the asc SCSI controller.
		More disk image filename prefixes are now recognized; c (for
		CD-ROM, as before), d for disk, b for boot device, r for
		read-only, and 0-7 for scsi id.
		Mounting disks works in Ultrix. Installing to disk usually
		crashes for various reasons, but an OSF/1 install gets
		relatively far (similar to the NetBSD/pmax install).
20040412	Trying to find the bug.
20040415	Finally found and fixed the bug; SCSI reads and writes
		(actually, any data in or data out) can be split up into
		multiple DMA transfers. That stuff was only partially
		implemented, and the part that was implemented was buggy.
		It works now. NetBSD/pmax and Ultrix 4.3 seems to like
		the SCSI stuff enough to install almost all the way.
20040415 (more)	Adding a hack which allows a host's cdrom device to be used as
		a cdrom device inside the emulator, eg /dev/cd0c.
		Making the cycle counter int64_t instead of long, as a 'long'
		overflows too easily on 32-bit machines. (The bug is still
		there, though.)
		I've now verified that a full NetBSD/pmax install can be done.
		If using a PMAG-AA graphics board, startx brings up X :-)
		mips64emul can be compiled inside NetBSD inside mips64emul,
		and it can run NetBSD in that environment. (I'm getting
		dizzy... :-)
20040417	Moving some coprocessor stuff from cpu.c to coproc.c.
20040424	Adding a BT455 vdac for PMAG-AA. Black and white are now
		rendered correctly in Xpmax.
		Adding colormap support to the BT459 device, for PMAG-BA.
20040425	Fixing a buffer length bug, which caused an Ultrix 4.5
		install to bug out on an i386 host.
20040429	FPU experiments.
20040502	More FPU experiments.
		Speedup for exception debug messages:  in quiet mode, debug
		messages were still evaluated, which took a relatively
		large amount of time.
20040503	Most FPU stuff fixed, but there is at least one known bug
		left; ps axu in NetBSD triggers it (ps loops forever).
20040504	A default install of Ultrix 4.5 succeeded! It boots up with
		a graphical login.
		Fixing the keyboard repetition bug (a lk201 "up" (release)
		scancode is now sent after every key).
20040505	Both CR and LF now produce the same lk201 scancode, so that
		pressing 'enter' works as expected in Ultrix.
20040506	Adding a vaddr to paddr translation cache, causing a speedup
		of perhaps 50% or more.
20040507	Fixing PMAG-BA color for Ultrix. (Ultrix relies on interrupts
		coming from the TURBOchannel slot to update the palette.)
20040508	Fixing cursor positioning for PMAG-BA.
20040511	Prints current nr of instructions per seconds, not only
		average, when using -N.
20040515	Some more bintrans experiments.
20040606	Adding ARCBIOS GetReadStatus() and Read().
		Adding some instructions: tlt, tltu, tge, tgeu, tne.
20040607	Adding the dsub instruction.
		Some minimal progress on SGI-IP30 emulation.
		Applying a patch from Juli Mallett to src/file.c (I'm not
		sure yet if it breaks or fixes anything).
		Some minor fixes for SGI-IP22 (such as faked board revision
		numbers).
20040608	ll/sc should now fail if any unrelated load/store occurs.
		Minor changes to the configure script.
		Adding some ifdefs around code which is not often used
		(the mfhi/mflo delay, and the last_used TLB experimental
		code); this might cause a tiny speedup.
20040609	Minor fixes.
20040610	Various minor SGI fixes (64-bit ARCS stuff, progress on the
		CRIME/MACE interrupt system, and some other random things).
20040611	More crime/mace progress, and some more work on pckbc.
		KN5800 progress: adding a XMI->BI adapter device; a disk
		controller is detected (but it is just a dummy so far).
20040612	Adding "dev_unreadable", which simplifies making memory
		areas unreadable. (NetBSD on SGI-IP22 no longer detects
		non-existant hpc1 and hpc2 busses.)
		Implementing rudimentary support for IP22 "local0" and
		"local1" interrupts, and "mappable" local interrupts.
		Some progress on the WDSC SCSI controller on IP22, enough
		to let NetBSD get past the disk detection and enter
		userland!  :-)
		The zs (zilog serial) device now works well enough to let
		NetBSD/sgimips be interacted with on IP22. :-)  (Though
		it is very ugly and hardcoded.)
20040613	IP32 didn't work last night, because there were too many
		tick functions registered. That has been increased now.
		Trying out NetBSD/sgimips 2.0 beta kernels. There are some
		differences compared to 1.6.2, which I'm trying to solve.
		Interrupt fixes for IP32: _serial and _misc are different.
		Separation of IP22 (Full-house) and IP24 (Guiness).
20040614	Modifying the memory layout for IP20,22,24,26 (RAM is now
		offset by 128MB, leaving room for EISA registers and such),
		and moving around some code chunks. This is not well
		tested yet, but seems to work.
		Moving parts of the tiny translation cache, as suggested
		by Juli Mallett.  It seems that the speedup isn't as
		apparent as it was a few weeks ago, though. :-(
		Speedups due to not translating addresses into symbol
		names unless the symbol name is actually printed.
		Added support for loading old big-endian (Irix) ECOFF
		kernels (0x60 0x01 as the first two bytes).
20040615 (late)	Adding enough SGI IP20 (Indigo) support to let NetBSD 2.0
		enter userland :-)  No interrupt specifics are implemented
		yet, so it hangs while doing terminal output.
20040618	Experimenting with the WDSC SCSI controller for IP20,22,24.
20040620	Adding a program which converts SGI prom dumps from text
		capture to binary, and some hacks to try to make such an
		IP22 PROM to work better in the emulator.
20040621	Removing the Nintendo 64 emulation mode, as it is too
		uninteresting to support.
		Adding SCSI tape device support (read-only, so far).
		Fixing a bug which caused the cursor to be corrupted if new
		data was written to the framebuffer, but the cursor wasn't
		moved.
20040622(early)	Finally! Making progress on the SCSI tape stuff; when going
		past the end of a file, automagically switch to the beginning
		of the next.
20040622(late)	Trying to track down the last SCSI tape bugs.
		Removing _all_ dynamic binary translation code (bintrans),
		starting from scratch again.
20040623(early)	Performing a general code cleanup (comments, fixing stuff
		that led to compiler warnings, ...).
		Disabling MIPS16 support by default, and making it a
		configure time option to enable it (--mips16). This gives
		a few percent speed increase overall.
		Increasing performance by assuming that instruction loads
		(reading from memory) will be at the same page as the last
		load.  (Several percent speedup.)
		Moving the list of kernels that can be found on the net from
		README to doc/.
20040624	Finally! I found and fixed the bug which caused 'ps', 'top',
		'xclock', and other programs in NetBSD/pmax to behave weird.
		Increasing performance by a few percent by running as many
		instructions in a row as possible, before checking for
		hardware ticks.
		When booting from SCSI tapes on DECstation, the bootstring
		now contains 'tz' instead of 'rz'.
		Adding a second ARC machine mode, "Acer PICA-61", -A2.
		Disabling the support for "instruction delays" by default
		(it has to be enabled manually in misc.h now, but is never
		used anywhere anyway).
		Other minor optimizations (moving around stuff in the
		cpu struct in misc.h, and caching cpu->pc in cpu.c).
		Separating the tiny translation cache into two, one for
		code and one for data. This gives a few percent speed
		increase.
20040625(early)	I think now is a good time for a "feature freeze",
		to let the code stabilize and then make some kind of
		first release.
20040625(later)	Adding a -v (verbose) command line option. If -v is not
		specified, the emulator goes into -q (quiet) mode just before
		it starts to execute MIPS code.
20040627	The configure script now adds -fomit-frame-pointer to the
		compile flags if the $CC seems to be able to handle that.
		Found and fixed a serious interrupt bug in BT459 (Ultrix'
		behaviour required a hack, which was incorrect), so
		performance for machines using the PMAG-BA framebuffer is
		now improved.
		For X11 bitdepths other than 8 or 24, a warning message
		is printed at startup.
		A number of other minor fixes, optimizations, updated
		comments and so on.
		Adding a BUGS file, a list of known bugs.
		Adding a minimal man page, doc/mips64emul.1.
20040628	Hacks for faking the existance of a second level cache
		(ARCBIOS and other places).
		An important fix for dc7085: tx interrupts should happen
		before rx interrupts, not the other way around as it was
		before. (This speeds up NetBSD boot on DECstation, and
		fixes a bug which Ultrix triggered on heavy keyboard input.)
		A couple of other minor fixes.
		Framebuffer fix: there was a bug which caused the rightmost/
		bottom pixel to sometimes not be updated, when running in
		scaledown mode. This is now fixed.
		Adding a small program which removes "zero holes" from
		harddisk image files.
20040629	More minor fixes.
20040629(later)	Adding -A3 (NEC RISCstation 2200) (this is similar to
		the 2250 model that NetBSD/arc can already boot all the
		way into userland and be interacted with), and -A4
		(Deskstation Tyne).
		Some more minor fixes.
20040630	Adding support for 15 and 16 bits X11 framebuffers,
		and converting from XYPixmap to ZPixmap (this fixes the
		problem of updates appearing in "layers" on some X
		servers).
		The pixels in the mouse cursor (for BT459) are now colored
		as the emulated OS sets them, although no transparency
		masking is done on the edges of the cursor yet. (In plain
		English:  the mouse cursor is no longer just a white solid
		square, you can actually see the mouse cursor image
		on the white square.)

==============  RELEASE 0.1  ==============

20040701	The -j option now takes a name, the of the kernel as passed
		on to the bootloader.  ("netbsd" is the default name.)
		Adding support to load bootstrap code directly from a disk
		image, for DECstation.  Both NetBSD/pmax and Ultrix boot
		straight of a disk image now, with no need to supply a
		kernel filename on the command line.  (Ultrix still needs
		-j vmunix, though, to boot from /vmunix instead of /netbsd.)
20040702	Minor bugfix (some new untested code for X11 keypresses was
		incorrect).
20040702(later)	Adding an ugly hack for CDROMs in FreeBSD; if an fread() isn't
		done at a 2048-byte aligned offset, it will fail. The hack
		tries to read at 2048-byte aligned offsets and move around
		buffers to make it work.
		Adding video off (screen blanking) support to BT459.

==============  RELEASE 0.1.1  ==============

20040702(later)	Cleanup to remove compiler warnings (Compaq's cc, Solaris' cc,
		and gcc 3.3.3/3.3.4 in Linux), mostly by putting ULL on large
		numeric constants.
		Better support for scaledown of BT459 cursors, but still not
		color-averaging.
		Beginning the work on adding better memory latency support
		(instruction delays), enabled by the --delays configure option.
20040703	Modifications to the configure script so that a config.h file
		is created, containing things that were passed along as
		-Dxxx on each cc command line before.
		More work on instruction latency support; trying to separate
		the concepts of nr of cycles and nr of instructions.
20040704	Working on R2000/R3000 caches.
		Adding a '--caches' option to the configure script.
		Various small optimizations.
		R3000 caches finally work. (I know that there is at least one
		bug, regarding interrupt response.)
20040705	Working on the 'le' device, and on a generic (device
		independant) networking framework. le can transmit and receive
		packets, and the network framework fakes ARP responses from a
		fake gateway machine (at a fixed ip address, 10.0.0.254).
		Adding a '-c' command line option, which makes emulated_hz
		automatically adjust itself to the current number of emulated
		cycles per host CPU second (measured at regular intervals).
20040707	Removing the '-c' option again, and making it the default
		behaviour of the emulator to automatically adjust clock
		interrupts to runtime speed (as long as it is above 1 MHz).
		(This can be overridden by specifying a static clock rate with
		the -I option.)
		Updating the doc/ stuff a bit.
		Generalization of the DECstation bootblock loading, to work
		with Sprite/pmax. Lots of other minor modifications to make
		Sprite work, such as adding support for DECstation "jump table"
		PROM functions, in addition to the old callback functions.
		Sprite boots from a disk image, starting the kernel if the
		argument "-j vmsprite" is used, but it seems to not like the
		DBE exceptions caused by reading empty TURBOchannel slots. :-/
20040708	Minor changes and perhaps some tiny speed improvements.
		The Lance chip is (apparently) supposed to set the length of
		received packets to len+4. (I've not found this in any 
		documentation, but this is what NetBSD expects.) So now, ICMP
		echo replies work :-)  UDP works in the outgoing direction,
		in the incoming direction, tcpdump can see the packets but they
		seem to be ignored anyway. (Weird.)
		Adding a separate virtual-address-to-host-page translation
		cache, 1-entry for loads, 1-entry for stores. (For now, it
		only works on R4000 as there are conflicts with cache usage
		on R3000).
		Changing the lower clock speed bound from 1 MHz to 1.5 MHz.
20040709	Incoming UDP checksums were wrong, but are now set to zero
		and NetBSD inside the emulator now accepts the packets (eg.
		nameserver responses).  Host lookups and even tftp file
		transfers (using UDP) work now :-)
		Adding a section on Networking to the Technical documentation,
		and a preliminary NetBSD/pmax install instruction for network
		installs to the User documentation.
		Some updates to the man page.
20040709(later)	Fix to the TURBOchannel code to allow Sprite to get past the
		card detection. Seems to still work with Ultrix and NetBSD.
		This also makes Linux/DECstation properly recognize both the
		Lance controller and the SCSI controller. Linux 2.4.26 from
		Debian boots nicely in framebuffer mode :-)
20040710	Some bits in the KN02 CSR that were supposed to be readonly
		weren't. That has been fixed, and this allows Linux/DECstation
		to get past SCSI detection. :-)
		Minor updates to the ASC controller, which makes Linux and
		OpenBSD/pmax like the controller enough to be able to access
		SCSI devices. OpenBSD/pmax boots from a disk image for the
		first time. :-)  Linux detects SCSI disks, but I have no
		bootable Linux diskimage to test this with.
		Updating the doc/ to include instructions on how to install
		OpenBSD/pmax onto a disk image.
		Naively added a PMAGB-BA (1280x1024x8) in hopes that it would
		basically be a PMAG-BA (1024x864x8) in higher resolution,
		but it didn't work that way. I'll have to look into this later.
		Adding a -o option, useful for selecting '-s' (single user
		mode) during OpenBSD install and other things.
		After a lot of debugging, a serious bug related to the tiny
		cache was found; Linux just changes the ASID and returns when
		switching between processes in some occasions without actually
		_writing_ to the TLB, and I had forgotten to invalidate the
		tiny cache on such a change.
20040711(early)	I've been trying to repeat the OpenBSD install from yesterday,
		but appart from the first initial install (which was
		successful), I've only been able to do one more. Several
		attempts have failed with a filesystem panic in the middle
		of install. I'm not sure why.
20040711	I found the "bug": wget downloaded the simpleroot28.fs.gz file
		as read-only, and gunzip preserved those flags. Thus, OpenBSD's
		installer crashed as it didn't get its writes through to the
		disk.
		Parts of the 1280x1024x8 PMAGB-BA graphics card has been
		implemented, it works (unaccelerated) in NetBSD and OpenBSD,
		but Ultrix does not seem to like it.
		Cleaned up the BT459 cursor offset stuff a bit.
		Trying to make the emulated mouse coordinates follow the host's
		mouse' coordinates (for lk201, DECstation), by
		"de-accelerating" the data sent to the emulated OS.
20040711(later)	Fix so that Sprite detects the PMAG-BA correctly.
		Adding some stuff about NFS via UDP to the documentation.
		Fixed the 'update flag' for seconds, so now Sprite doesn't
		crash because of timer-related issues anymore.
		Fixing KN02 interrupt masks a bit more, to make Sprite not
		crash. Sprite now runs quite well.
20040712	Working on IP/UDP fragementation issues. Incoming UDP packets
		from the outside world can now be broken up into fragments
		for the guest OS. (This allows, for example, OpenBSD/pmax to
		be installed via nfs.)  Outgoing fragmented packets are NOT
		yet handled.
		Linux doesn't use 64-bit file offsets by default, which is
		needed when using large disk images (more than 2GB), so the
		configure script has now been modified to add necessary
		compiler flags for Linux.
20040713	Trying out some minor optimizations.
		Refreshing the UDP implementation in src/net.c a little.
20040714	Updating the documentation a little on how to experiment
		with a Debian Linux install kernel for DECstations.
		A 'mini.iso' Linux image for DECstation has different fields
		at offsets 0x10 and 0x14, so I'm guessing that the first is
		the load address and the second is the initial PC value.
		Hopefully this doesn't break anything.
		Some initial TCP hacks, but not much is working yet.
		Some updates for IP30:  The load/store 1-entry cache didn't
		work too well with IP30 memory, so it's only turned on for
		"MMU4K" now. (This needs to be fixed some better way.)
		Adding a hack which allows Linux/Octane to use ARC write()
		and getchild() on IP30. Linux uses ARCBIOS_SPB_SIGNATURE as a
		64-bit field, it was 32-bit before.
		Making ugly hacks to the arcbios emulation to semi-support
		64-bit equivalents of 32-bit structures.
20040716	Minor fixes to the configure script (and a few other places)
		to make the sources compile out-of-the-box on HP-UX (ia64
		and HPPA), old OpenBSD/pmax (inside the emulator itself), and
		Tru64 (OSF/1) on Alpha.
		A couple of other minor fixes.
20040717	A little TCP progress; OpenBSD/pmax likes my SYN+ACK replies,
		and tries to send out data, but NetBSD/pmax just drops the
		SYN+ACK packets.
		Trial-and-error led me to change the 64-bit ARCS component
		struct again (Linux/IP30 likes it now). I'm not sure about all 
		of the offsets yet, but some things seem to work.
		More 64-bit ARCS updates (memory descriptors etc).
		Better memory offset fix for IP30, similar to how I did it for
		IP22 etc. (Hopefully this doesn't break anything else.)
		Adding a MardiGras graphics controller skeleton for SGI-IP30
		(dev_sgi_mardigras.c).
		Thanks to Stanislaw Skowronek for dual-licensing mgras.h.
		Finally rewrote get_symbol_name() to O(log n) instead of O(n)
		(Stanislaw's Linux kernel had so many symbols that tracing
		with the old get_symbol_name() was unbareably slow).
		Removing all of the experimental tlbmod tag optimization code
		(the 1-entry load/store cache), as it causes more trouble than
		the performance gain was worth.
20040718	The MardiGras device works well enough to let Linux draw the
		SGI logo and output text.
		A bunch of other minor changes.
20040719	Trying to move out all of the instruction_trace stuff from the
		main cpu loop (for two reasons: a little performance gain,
		and to make it easier to add a GUI later on).
20040720	Finally found and fixed the ethernet/tcp bug. The hardware
		address is comprised of 6 bytes, where the _first_ byte should
		have a zero as the lowest bit, not the last byte. (This causes
		NetBSD and Linux running in the emulator to accept my SYN+ACK
		packets.)
		Getting the first nameserver address from /etc/resolv.conf.
		(This is not used yet, but could be useful if/when I add
		internal DHCP support.)
		Working more on the TCP stuff; TCP seems to be almost working,
		the only immediate problem left is that the guest OS gets
		stuck in the closing and last-ack states, when it shouldn't.
		It is now possible to install NetBSD and OpenBSD via ftp. :-)
20040721	Trying to fix the last-ack bug, by sending an RST after the
		end of a connection. (Probably not a correct fix, but seems
		to work?)
		Adding a my_fseek() function, which works like fseek() but
		with off_t instead of long, so that large disk images can
		be used on systems where long is 32 bits.
20040722	Trying to fix some more TCP related bugs.
20040725	Changing the inlined asm statement in bintrans_alpha.c into
		a call to a hardcoded array of bytes that do the same thing
		(an instruction cache invalidation). This allows the same
		invalidation code to be used regardless of compiler.
		Some other minor changes.
20040726	Minor updates. The configure script is now more verbose.
		A Debian/IP22 Linux tftp boot kernel requires ARCS memory to
		be FreeMemory, not FreeContiguous. (This should still work with
		other SGI and ARC OSes.)
		Fix for ARCS write(), so it returns good write count and
		success result (0).
		Some hacks to the IP22 memory controller, to fake 72MB RAM
		in bank 0.
		The IP22 Debian kernel reaches userland (ramdisk) when run
		with -G24 -M72 -CR4400, if a special hack is done to the
		zs device.
20040730	Removing mgras.h, as I'm not sure a file dual-licensed this way
		would work. (Dual-licensing as two separate files would work
		though.)
		Preparing for the upcoming release (0.2).
20040801	Fixing the 512 vs 2048 cdrom sector size bug; I hadn't 
		implemented the mode select SCSI command. (It still isn't
		really implemented.)
		A bug which crashes the emulator is triggered when run with
		new NetBSD 2.0_BETA snapshots on a Linux/i386 host. I'm not
		sure why.
		UDP packets sent to the gateway (at 10.0.0.254) are now
		forwarded to the machine that the host uses as its nameserver.
		Some other minor fixes.

==============  RELEASE 0.2  ==============

20040803	A post-3.5 OpenBSD/sgimips kernel snapshot with ramdisk seems
		to boot fine in the emulator, all the way to userland, and
		can be interacted with.
		Adding a -y option, used to set how many (random) instructions
		to run from each CPU at max (useful for SMP instruction
		interleave experiments).
		Importing a 8x16 console font from FreeBSD (vt220l.816).
		Adding a skeleton for a 80x25 text console device (dev_vga),
		useful for some ARC modes. (Character output is possible, but
		no cursor yet.)
		Adding a dev_zero device (returns zeroes on read).
		OpenBSD/arc 2.3 can get all the way to userland with -A4 (if
		the wdc devices are commented out) but bugs out there, probably
		because of interrupt issues.
		Adding a -A5 ARC emulation mode (Microsoft-Jazz, "MIPS Magnum")
		which NetBSD seems to like. No interrupt specifics yet, so
		it hangs while waiting for SCSI.
20040804	Some dev_mp updates.
		The -y switch has to do with number of cycles, not number
		of instructions; variable names have been changed to reflect
		this.
20040805	Minor updates. Adding some more CPU types/names, but they
		are probably bogus.
		Adding a MeshCube emulation mode. Just a skeleton so far, but
		enough to let a Linux kernel print some boot messages.
		Adding the 'deret' instruction.
20040806	Adding include/impactsr-bsd.h (a newer version of what was in
		mgras.h before, and this time with only a BSD-style license),
		but it is not used yet.
20040810	Some Au1500 updates.
20040811	Adding the 'clz', 'clo', 'dclz', and 'dclo' special2 (MIPS32
		and MIPS64) instructions.
		More Au1500 updates.
20040812	Using fseeko(), when it is available.
		Other minor updates.
		Adding a NetGear WG602 emulation mode skeleton (-g); after
		a lot of trial and error, a Linux kernel (WG602_V1715.img)
		gets all the way to userland, but hangs there.
20040818	Adding signal handlers to better cope with CTRL-Z and CTRL-C.
		Adding a simple interactive single-step debugger which is
		activated by CTRL-C. (Commands so far: continue, dump, help,
		itrace, quit, registers, step, trace, version)
20040818(later)	Adding a 'tlbdump' debugger command, and some other minor
		fixes.
20040819	Minor updates. Adding an 'unassemble' debugger command.
20040822	Minor updates to the regression testing framework.
20040824	Minor updates based on feedback from Alec Voropay
		(configure script updates for Cygwin and documentation).
20040826	Minor updates.
		Adding a cursor to the VGA text console device.
		Changing all old 11:22:..55:66 ethernet macs to 10:20..60,
		still hardcoded though.
20040828	Minor updates.
20040829	mips64emul is 1 year old today :-)
20040901	tests/README now lists "all" MIPS opcodes. This list should
		be updated whenever a new opcode is implemented, or when a
		regression test is added. (A combination of instructions from
		the TX79 manual, the GNU assembler, and the MIPS64 manual).
		Hopefully I haven't missed too many.
		Adding a section on regression testing to doc/technical.html.
20040902	Finally beginning the work on separating out the stuff from
		main.c into a "struct emul". Very time-consuming.
		Some minor fixes for LL/SC on R10000.
20040905	Moving more stuff from main.c into struct emul. Unfortunately,
		it seems that this causes a slowdown of the emulator.
		Userland emulation is now only used if --userland is used
		when running configure.
		Modifying src/symbol.c to not use global variables.
20040906	Minor update.
20040914	Using $COPTIM when detecting which compiler flags to use in
		the configure script. (This makes sure that combinations of
		flags should work.)
		There'll probably be a 0.2.1 release some time soon, but I'll
		do some more clean-up first.
		Minor update to the detection of ECOFF files, but I don't like
		it; sometimes the endianness of the magic value seems to be
		swapped, but it doesn't have to do with endianness of the
		actual data?
20040916	Minor updates. Adding an Example section to the manpage, but
		as I'm not really familiar with manpage formatting, it will
		need to be rewritten later.
20040917	Finally making the coprocessor instructions disassemblable
		even when not running.
		Doing some testing for the 0.2.1 release.

==============  RELEASE 0.2.1  ==============

20040923	Updating the documentation about how to (try to) install
		Debian GNU/Linux.
20040924	Some more updates to the documentation.
20040925	Adding overflow stuff to 'add' and 'sub'.
20040926	Minor updates: possibly a fix to 'sltiu' (the imm value
		should be treated as signed, and then converted to unsigned,
		according to the MIPS64 manual), and removing the
		'last_was_rfe' stuff (again).
		OpenBSD/arc used speed-hack jumps with other deltas than just
		+/- 1 (it used -3 iirc), so the jump speedhack should now
		support any delta. Also adding bgtzl and blezl as possible
		instructions for the speed-hack jumps. (This needs to be
		tested more.)
20040928	Minor updates. Some ARC stuff ("arcdiag" runs now).
		cpu_register_dump() now also dumps coprocessor registers.
20040929	More ARC updates. Making the code look a tiny bit nicer
		than before. "arcdiag.ip22" works for -G22 (SGI-IP22).
		Apparently the overflow support in the 'add' instruction
		was incorrect, so I disabled it.
20041002	Trying to install Ultrix in the emulator, but the installer
		crashes; found (and fixed) the bug rather quickly: the "fix"
		I implemented a few days ago for the 'sub' instruction
		(according to the MIPS64 manual) caused the bug.
20041004	Changing the behaviour of the -j command line option. The
		default is now "" (or taken from the last filename given on
		the command line), not "netbsd". In practice, this doesn't
		change much, except that -j netbsd.pmax is no longer needed
		when installing NetBSD.
		Adding a COMPILE_DATE string to config.h.
20041007	Adding a NEC RISCserver 4200 model (-A6), and some more
		updates to the ARC component tree generator.
20041008	The 'll' instruction should be signed, not unsigned as before.
		This (and some other minor fixes) causes Irix on SGI-IP32 (O2)
		to actually boot far enough to print its first boot messages :)
		Working on some new dynamic bintrans code. Enough is now
		implemented so that the 'nop' instruction is translated
		and there is support for Alpha, i386 and UltraSparc backends,
		but performance is about 50% worse than when running without
		bintrans. (This is as expected, though.)
20041009	Minor updates to the documentation.
		Using mprotect() to make sure that the code created dynamically
		by the bintrans subsystem is allowed to be executed. (This
		affects newer OpenBSD systems, and possibly others.)
		The translated code chunks now only get one argument passed to
		them, the (struct cpu *) of the current cpu.
20041010	Hack to dev_le.c which makes Ultrix accept the initialization
		of the LANCE controller. (This goes against the LANCE
		documentation though.)
		In src/net.c, a fix for Ultrix (which seems to send larger
		ethernet packets than the actual TCP/IP contents). The hack to
		dev_le.c and this fix is enough to let Ultrix access the
		Internet.
		For DECstation, when booting without a disk image (or when
		"-O" is used on the command line), use "tftp" instead of "rzX"
		for the boot string.
20041011	Adding cache size variables to the emul struct, so that these
		can be set on a per-machine basis (or potentially manually
		on the command line).
20041012	Mach/PMAX now passes the LK201 keyboard self-test (although
		the keyboard ID is still bogus).
20041013	Minor updates.
		Hacks to the ASC SCSI controller for Mach/PMAX, hopefully this
		will not break support for other OSes.
20041014	Minor fix to src/emul.c for reading bootblocks at the end of
		a disk or cdrom image (thanks to Alexandru Lazar for making me
		aware of this).
		Adding "gets()" to src/dec_prom.c.
		Working a bit on ARC stuff. Importing pica.h from NetBSD.
		Minor updates to the ARC component tree for PICA-61.
		Adding a dev_jazz.c (mostly for PICA-61).
		Renaming dev_jazz.c into dev_pica.c. Working on PICA timer
		and interrupt specifics.
20041016	Adding some dummy entries to lk201.c to reduce debug output.
		Some bintrans updates (don't run in delay slots or nullified
		slots, read directly from host memory and not via memory_rw(),
		try mmap() before malloc() at startup, and many other minor
		updates).
		Adding bintrans_mips.c for 64-bit MIPS hosts, but it is not
		used yet.
20041017	Minor updates.
20041018	Update to dev_mc146818 to allow Mach to boot a bit further.
		The "hardware random" in dev_mp.c now returns up to 64 bits
		of random.
20041019	Minor updates to the way cache sizes are used throughout the
		code. Should be mostly ok for R[234]x00.
		src/file.c now loads files using NO_EXCEPTIONS. Whether this
		is good or bad, I'm not sure.
20041020	Adding a Linksys WRT54G emulation skeleton (-H).
20041021	Minor updates.
		R1[024]000 cache size bits in the config register should now
		be ok.
		Trying to make dev_asc.c work better with PICA.
		More work on PICA interrupts (but they are broken now).
20041022	Generalizing the dev_vga text console device so that it can be
		used in other resolutions than just 80x25. Works with
		OpenBSD/arc.
		emul->boot_string_argument is now empty by default (except
		for DECstation modes, where it is "-a").
		Speedup of dev_ram by using mmap() instead of malloc().
		Using mmap() in memory.c as well, which reduces memory usage
		when emulating large memory sizes if the memory isn't actually
		written to.
20041023	Minor updates.
20041024	Updates to the PC-style keyboard controller, used by PICA.
		Updates to the PICA (Jazz) interrupt system. Both NetBSD/arc
		and OpenBSD/arc now reach userland with PICA emulation, and
		can be interacted with (there are a few programs on the
		INSTALL kernel ramdisks). In the case of OpenBSD, a VGA text
		console and PC-style keyboard controller is used, NetBSD
		runs on serial console.
		Adding a framework for DMA transfer for the ASC SCSI
		controller.
		Implementing a R4030 DMA controller for PICA, enough to let
		OpenBSD/arc and NetBSD/arc be installed on an emulated
		Pica. :-)
		Updates to the documentation.
20041025	Working on ISA interrupts for PICA.
		Adding an Olivetti M700 emulation mode (-A7).
		Better separation of PICA and M700 stuff (which I accidentally
		mixed up before, I thought the M700 Linux kernel would 
		also work on PICA because it almost booted).
		Writing a skeleton G364 framebuffer for M700, enough to show
		the Linux penguin and some text, although scrolling isn't
		correctly implemented yet.
		Adding a dummy SONIC (ethernet) device, dev_sn, for PICA.
		Fixing the passing of OSLOADOPTIONS for ARC, the default is
		now "-aN" which works fine with OpenBSD/arc and NetBSD/arc.
20041027	Minor updates.
20041029	Adding a Sony NeWS "newsmips" emulation mode skeleton (-f).
		Found and fixed a bug which prevented Linux/IP32 from running
		(the speed-hack-jump-optimization fix I made a few weeks ago
		was buggy).
		Adding the trunc.w.fmt and trunc.l.fmt instructions, although
		the are probably not really tested yet.
		Changes to how floating point values are handled in
		src/coproc.c, but right now it is probably very unstable.
20041101	I had accidentally removed the instructions on how to install
		Ultrix from doc/index.html. They are back now.
		Adding a -Z option, which makes it easier to run dual- or
		tripple-head with Ultrix. (Default nr of graphics cards
		without -X is 0, with -X is 1.)
		Minor update which makes it possible to switch to the left
		monitor when running tripple-head, not just right as before.
		When using more than one framebuffer window, and the host's
		mouse cursor is in a different window than the emulated mouse
		cursor, the emulated mouse will now try to move "very far",
		so that it in practice changes screen.
		Running Ultrix with dual- and tripple-head now feels really
		great.
20041101(later)	OpenBSD/arc and Linux/Olivetti-M700 don't both work at the
		same time with the speed-hack stuff. So, from now on, you
		need to add -J for Linux, and add nothing for openbsd.
20041102	Minor update for OSF/1 V4.0 (include sys/time.h in src/net.c
		and add -D_POSIX_PII_SOCKET to the C compiler flags).
20041103	Minor updates for the release.
		For some reason, Mach/PMAX caused the emulator to bug out on
		SunOS/sparc64 (compiled in 64-bit mode); a minor update/hack
		to dev_asc fixed this.

==============  RELEASE 0.2.2  ==============

20041103	Minor updates.
20041104	Minor updates.
20041105	Running with different framebuffer windows on different X11
		displays works now (even with different bit depths and
		endiannesses on different displays). A new command line option
		(-z) adds DISPLAYs that should be used.
		Update regarding how DECstation BT459 cursors are used;
		transparency :-) and some other bug fixes.
20041106	More bt459 updates. The cursor color seems to be correct for
		NetBSD, OpenBSD, Ultrix, and Sprite.
		Some minor bintrans updates (redesigning some things).
20041107	More bintrans updates (probably broken for non-Alpha targets).
		Moving doc/mips64emul.1 to man/.
20041108	Some updates.
20041109	More updates. Bintrans experiments mostly.
20041110	Some minor bintrans updates.
20041111	Minor updates.
20041112	A little rewrite of the bintrans system (again :-), this time
		a lot more naďve and non-optimizing, in order to support delay
		slots in a much simpler way.
		Ultrix 4.5 boots into a usable desktop on my home machine in
		3min 28sec, compared to 6-8 minutes without bintrans.
20041113	Some minor bintrans updates.
20041114	More bintrans updates. Ultrix now boots in exactly 3 minutes
		on my home machine.
20041115	More bintrans updates.
20041116	Bintrans updates.
20041117	Working on dev_dec_ioasic and related issues.
		Adding support for letting translated code access devices in
		some cases (such as framebuffers).
20041118	Moving some MIPS registers into Alpha registers, which gives
		a speed improvement.
		Beginning to write an i386 bintrans backend. Skeleton stuff
		works, lui, jr/jalr, addiu/daddiu/andi/ori/xori, j/jal,
		addu/daddu/subu/xor/or/nor/and.
20041119	dsubu/sll/srl/sra, rfe,mfc0,dmfc0, beq,bne, delayed branches.
		Some load/store (but not for bigendian emulation yet.)
		Time to reach Ultrix 4.5's graphical login on a 2.8 GHz Xeon
		host is now down to 20 seconds!
		Adding bgez, bltz, bgtz, and blez to the i386 backend.
20041120	Minor updates (bintrans related mostly).
		Time to reach Ultrix login on the Xeon is now 11 seconds.
		Adding 'mult', 'multu' and a some parts of mtc0 to the Alpha
		backend.
		The transparency updates to the X11 cursor support made the
		OpenBSD/arc cursor disappear; that has been fixed now.
		Unfortunately, something with Acer Pica emulation is broken
		when bintrans is enabled.
20041121	Making tlbwr, tlbwi, tlbp, tlbr callable directly from
		translated code.
		Adding sltiu, slti, slt, and sltu to the i386 backend.
20041122	More bintrans updates.
		With the Alpha backend, the status and entryhi registers
		can (in some cases) be written without exiting to the main
		loop. Ultrix boot time until a usable desktop is reached
		is about 1 min 35 seconds on the 533 MHz pca56.
		Adding srlv, srav, and sllv to the i386 backend.
20041123	Removing the special handling of high physical addresses for
		DECstation emulation from the main memory handling code, and
		replacing it with a mirror device instead. (This results in
		a tiny increase in performance, and cleaner code.)
		Various minor updates.
20041124	Ripping out _all_ bintrans load/store code, because I have
		a new idea I'd like to try out.
		A total rewrite of the load/store system. It works when
		emulating 32-bit MIPS, but not for 64-bit code yet.
		Some minor updates to the dev_fb, but no speed improvement.
		Making the 'le' ethernet device' SRAM work with bintrans.
20041125	Various updates.
		Adding a little "bootup logo" to the framebuffer.
		There is now one translate_address() for R3000-style MMUs,
		and one for the other types. (This gives a tiny speed
		improvement.)
20041126	Minor updates, bintrans.
		Fixing the bug which caused OpenBSD/arc (R4000) to bug out;
		it was introduced between the 7:th and 10:th of November
		when moving up the check for interrupts to above the code
		which runs bintrans code, in src/cpu.c.
		Adding movn and movz to the Alpha bintrans backend.
20041127	Various minor updates.
20041128	Making the R2000/R3000 caches work with bintrans, even in
		isolated mode. (Not true cache emulation, but it works with
		NetBSD/pmax, OpenBSD/pmax, and Ultrix.)
		Making the default cache size for R3000 4KB instr, 4 KB data;
		a real R3000 could have 64KB each, but emulated OSes run
		faster when they think the cache is smaller :-)
		Updates to the i386 backend: the nr of executed instructions
		is now placed in ebp at all times, and some support for
		mtc0 similar to how it is done in the Alpha backend has been
		added. A full NetBSD/pmax 1.6.2 install can now be done in
		5 minutes 35 seconds, on a 2.8 GHz Xeon host (with -bD2 -M20).
		Adding mult and multu to the i386 bintrans backend.
		Reducing the number of malloc/free calls used by the
		diskimage subsystem.
20041129	Minor updates to the Alpha bintrans backend.
20041130	Trying to fix the bug which prevents Linux from working
		with bintrans. It _seems_ to work now. (Pages could in some
		cases be written to after they were translated, but that
		has been fixed now.)
		A couple of other minor fixes.
		Minor updates to the Alpha backend (directly using Alpha
		registers in some cases, instead of loading into temporaries).
		Updates to the i386 backend (special hacks for 32-bit
		MIPS emulation, which are fast on i386, for example only
		updating half of the pc register).
20041201	More updates to the i386 backend, similar to those yesterday.
		Preparing for release 0.2.3.
		Adding a generic load/store mechanism, which is used when the
		32-bit optimized version cannot be used (for R4000 etc).

==============  RELEASE 0.2.3  ==============

20041202	If ALWAYS_SIGNEXTEND_32 is defined in misc.h, and an
		incorrectly extended register is detected, the emulator now
		exits instead of continues.
		Removing the LAST_USED_TLB_EXPERIMENT stuff.
		Minor updates to work better with Windows NT's ARCINST.EXE;
		printing 0x9b via arcbios becomes ESC + '[', and the ARC
		memory descriptor stuff has been generalized a bit more.
		Adding arbios hacks for Open(), Seek(), GetRelativeTime(),
		and Read() to allow WinNT's SETUPLDR to read the filesystem
		on the diskimage used for booting.
20041203	Adding a terminal emulation layer which converts arcbios
		stdout writes to "VGA text console" cell characters. Seems
		to work with Windows NT and arcdiag.
		Adding a 8x8 font to dev_vga.
		Adding more ARC components to the component tree (for PICA
		emulation).
20041204	Minor updates.
		More updates to dev_vga. Adding a 8x10 font.
		Adding a hack so that the framebuffer logo is visible at
		startup with dev_vga. (It disappears at the first scroll.)
		A minor fix for a bug which was triggered when running
		dual- or tripple-head, on 2 or 3 actual X11 displays.
20041205	Fixing a bintrans bug.
		Some other minor updates (some of them bintrans related).
20041206	Moving the web page to http://gavare.se.
		Adding a hack for mmap() which supports anonymous mapping
		using /dev/zero, but not using MAP_ANON{,YMOUS}.
		Separating out opcodes.h, cop0.h, and cpu_types.h from misc.h.
20041207	Minor bintrans update. (In some cases, it isn't necessary
		to return to the main loop, when translating from a new page.)
		Some other minor i386 bintrans backend optimizations.
		And some other minor updates.
		i386 backend update: the lowest 32 bits of the pc register
		are now placed in an i386 register.
20041208	Adding GetConfigurationData() and some support for config
		data, to src/arcbios.c.
		Adding a bogus 0xbd SCSI command (used by Windows NT). It is
		not listed in http://www.danbbs.dk/~dino/SCSI/SCSI2-D.html.
		If the framebuffer cursor contains more than 1 color, then
		the host's X11 cursor disappears. (Nice for DECstation
		emulation with emulated X.)
		For ARC and SGI emulation, if an exception occurs before an
		exception handler is installed, the emulator now exits
		nicely (as suggested by Alec Voropay).
		A couple of minor updates to the ARCBIOS emulation subsystem.
		The single step debugger is now automatically entered when
		all CPUs have stopped running, unless there was a clean
		shutdown of some kind (PROM halt() call, or similar).
		Adding a -V option for starting up in a paused state, into
		the single-step debugger.
		Adding a note about 'mmon' to the documentation
		(http://www.brouhaha.com/~eric/software/mmon/).
20041209	Fixes to devices/console.c which makes cursor keys and such
		a bit more reliable.
		ARCBIOS hack/update which creates memory descriptors _after_
		loading the executable. (Seems to work with OpenBSD/arc,
		NetBSD/arc, arcdiag, IRIX, NetBSD/sgimips, OpenBSD/sgi, and
		some Windows NT executables.)
		ARCBIOS support for cursor keys (ESC + '[' ==> 0x9b).
		A bintrans update (for 32-bit emulation) which speeds up
		jumps between pages, if code is already translated.
		Changing the default bintrans cache from 20 to 24 MB.
20041210	Optimizing unaligned load/stores a little bit in src/cpu.c.
		Omiting the check for nr of executed bintrans instructions
		on some forward jumps.
		Adding the 'syscall' and 'break' instructions to the
		bintrans backends.
		Allowing more bits of the status register to be written to
		from within inside translated code, on R3000.
		Getting rid of the final pixel when hiding the host's mouse
		cursor.
		store_buf() now copies data 8 or 4 bytes at a time, when
		possible. (This speeds up emulated ROM disk reads, etc.)
		Tiny bug fix: coprocessor unusable exceptions are now also
		generated (for coproc 1..3) even when in kernel mode, if the
		coprocessors are not enabled. This allows a Debian installation
		to proceed further than before. (It's still very unstable,
		though.)
20041212	Updating doc/index.html with better Debian installation
		instructions.
		If SLOWSERIALINTERRUPTS is defined at compile time, interrupts
		from the dc7085 device will not come as often as they normally
		do. This makes Debian seem more stable.
		Decreasing the bintrans cache to 20 MB again.
		Updating some files in preparation for a 0.2.4 release.
20041213	Updating the docs on how to install NetBSD 2.0/pmax, and also
		some updates to the section on installing Debian.
		32-bit bintrans backend optimization: don't inline large
		chunks of code, such as general jumps.
20041214	Minor fix for coproc unusable for R4000 (it's the PC that,
		matters, not the KSU bits).
		Separating out the debugger from emul.c into debugger.c.
		Rewriting parts of the debugger.
		Removing the -U command line option, as it wasn't really
		useful. Also removing the -P option.
		Renaming all instances of dumppoint to breakpoint, as that
		is what it really is.
		When a breakpoint is reached, the single-step debugger is
		entered, instead of just turning on instruction trace.
		Adding a 'breakpoints' debugger command.
		Better fix for coproc unusable on R4000: the KSU bits matter,
		but the ERL and EXL bits override that.
		Fix which allows Debian to boot directly from a disk image
		(with DELO). (It reads multiple separate areas from disk.)
		Update to the SLOWSERIALINTERRUPTS stuff, making it even
		slower.
		Fixes based on feedback from Alec Voropay (-Q with ARC
		emulation skips the setup of arcbios data structures in
		memory, and no sign-extension _after_ writing a 32-bit
		value to a 64-bit coproc 0 register).
		Adding a 'devices' command to the debugger.
		The 'registers' and 'tlbdump' commands now take an optional
		argument (a cpu id).
		Adding rudimentary tab-completion and cursor key stuff to
		debugger_readline().
		Adding some more debugger commands: 'bintrans' and 'machine'.
20041215	Adding a 'devstate' command; implementing a skeleton for a
		state function for the bt459 device.
		Implementing yet another variant of the SLOWSERIALINTERRUPTS
		stuff.
		Implementing more of the different exception offsets (taking
		CAUSE_IV and STATUS_BEV into account).
		hpc_bootinfo should now be correctly filled on big-endian
		hosts.
		Always shift left by 12, not by pageshift, to get physical
		addresses on MMU4K etc. (Thanks to Alec Voropay for noticing
		this.)
20041216	The KN02's CSR can now be read from bintranslated code.
		Adding a dummy dev_sgi_mec.
20041217	The default framebuffer and model settings for -F (hpcmips)
		should now be almost like Cassiopeia E-500.
		Changing -DSLOWSERIALINTERRUPTS into a command line option, -U.
20041218	Continuing a little bit on the mec controller.
		Removing lots of #include <math.h> that weren't really used.
20041219	Fixing stuff that broke because of the pageshift bugfix.
		Adding an argument to the s (step) debugger command, for doing
		more than 1 step at a time.
		ARCBIOS components representing disk images are now created
		to actually match the disk images in use, and some other
		arcbios-related updates; adding a dummy GetComponent().
		Adding a 'lookup' command to the debugger, for symbol lookups.
		Adding a "NEC Express RISCserver" mode (NEC-R96, -A8).
		Adding a dummy ARCBIOS GetFileInformation(), GetTime(), and
		SetEnvironmentVariable().
20041220	Improved command line editing (including command history)
		in the debugger.
		Separating some more .h files from each other, and fixing
		some Solaris compiler warnings.
20041221	Minor updates.
20041222	Minor updates; hpcmips (BE300, VR41xx) stuff.
		The 'register' debugger command is now 'reg', and it can
		be used to modify registers, not just read them.
		The syntax for hpcmips (-F) is now -F xx, where xx is a
		machine model identifier. (1 = BE300.)
20041223	Some really minor updates.
20041226	Minor updates to doc/index.html (NetBSD 1.6.2 -> 2.0, and
		some other rearrangements).
		Many updates to the debugger (better register manipulation,
		breakpoint manipulation, and other updates).
		Fix to dev_cons.c to allow the regression tests to work again.
		The configure script now tries to detect the presence of a
		MIPS cross compiler. (Used by "make regtest".)
		Regression tests are now run both with and without bintrans.
20041227	Some hacks to the VR41xx code to allow Linux for BE300 to
		get far enough to show the penguin on the framebuffer.
20041228	Merging dev_kn01_csr.c and dev_vdac.c into dev_kn01.c.
20041229	Various updates to the debugger (nicer tlb output and other
		things).
		Some floating point fixes in src/coproc.c (mov is not
		an arithmetic instruction), and in src/cpu.c (ldcX/sdcX in
		32-bit mode uses register pairs).
		'-O' now also affects the bootstring for SGI and ARC emulation.
		Bintrans updates (slightly faster 32-bit load/store on alpha).
		Updates to the i386 backend too, but no real speed improvement.
20041230	Cleaning up parts of the 64-bit virtual-to-physical code for
		R10000, and per-machine default TLB entries can now be set
		for SGI and ARC machines.
		Fix: SGI-IP27 is ARC64, not ARCS.
20050101	Minor updates.
20050102	Minor updates.
		Fixing a 32-bit 'addu' bug in the bintrans backends.
		Allowing fast load/stores even in 64-bit bintrans mode, if
		the top 32 bits are either 0x00000000 or 0xffffffff (for Alpha
		only).
		Re-enabling ctc0/cfc0 (but what do they do?).
		Adding beql, bnel, blezl, and bgtzl to the Alpha backend.
20050103	Adding fast 32-bit load/store for 64-bit mode emulation to
		the i386 backend too (similar to the Alpha code). Not really
		tested yet, though.
		Adding an incomplete regression test case for lwl/lwr/ldl/ldr.
		Playing around with bintranslated lwl and lwr for Alpha.
20040104	Changing many occurances of pica to jazz.
		Various other updates.
20050105	Fixing some more bintrans bugs (both Alpha and i386).
		Unaligned stores that cause tlb refill exceptions should now
		cause TLBS exceptions, not TLBL.
		Adding experimental swl and swr to the Alpha backend.
		Adding lwl, lwr, swl, and swr to the i386 backend.
20050106	Adding another hpcmips model (Casio E-105, -F2), and doing
		some updates to the VR41xx code. NetBSD/hpcmips prints some
		boot messages.
20050108	Minor updates.
20050109	dev_dec5500_ioboard.c and dev_sgec.c => dev_kn220.c.
		dev_crime.c, _mace.c, and _macepci.c => dev_sgi_ip32.c.
		Also adding dev_sgi_mec, _ust, and _mte into dev_sgi_ip32.c.
		A slight license change. Still revised BSD-style, though.
		memory_v2p.c is now included separately for MMU10K and
		MMU8K.
		Fixing a NS16550 bug, triggered by NetBSD 2.0, but not 1.6.2.
		Refreshing the UltraSPARC bintrans backend skeleton.
		Merging dev_decbi, _deccca, and _decxmi into dev_dec5800.c.
		Sparc backend instructions done so far: mthi/mtlo/mfhi/mflo,
		lui, addu, daddu, subu, dsubu, and, or, nor, xor, sll, dsll,
		srl, and sra.
		Adding more sparc backend instructions: addiu, daddiu, xori,
		ori, andi, srlv, srav, sllv, slt, sltu, slti, sltiu.
20050110	Changing the default bintrans cache to 16 MB, and some other
		minor updates.
		Adding div and divu to the i386 backend (but not Alpha yet).
		More work on ARCBIOS emulation.
		Trying to find a bug which affects Linux on Playstation 2 in
		bintrans mode.
20050111	Moving around some Playstation 2 stuff, but I haven't found
		the bug yet. It is triggered by load/stores.
		More ARCBIOS updates, enough to let Windows NT partition
		disks in some rudimentary fashion.
20050112	Testing for release 0.2.4.
		Fixes to suppress compiler warnings.

==============  RELEASE 0.2.4  ==============

20050113	Minor updates.
20050114	Fix to the Alpha bintrans backend to allow compilation with
		old versions of gcc (2.95.4).

==============  RELEASE 0.2.4.1  ==============

20050115	Various updates and fixes: some IP32 stuff, the debugger,
		ns16550 loopback tx isn't transmitted out anymore, ...
		Removing old/broken R10000 cache hacks, which weren't really
		used.
20050116	Minor updates to the documentation on using PROM images.
		Adding ARCBIOS function 0x100 (used by IRIX when returning
		from main, but undocumented).
		MC146818 updates (mostly SGI-related).
		ARCS64 updates (testing with an OpenBSD snapshot in IP27
		mode). This causes Linux/IP30 to not work. Maybe IP27 and
		IP30 differ, even though both are 64-bit?
		Removing some nonsensical ARCS64 code from machine.c.
		Better handling of 128MB and 512MB memory offsets used by
		various SGI models.
		Trying to revert the ARCS64 changes (OpenBSD/sgi does
		seem to be aware of 64-bit vs 32-bit data structures in
		_some_ places, but not all), to make Linux/IP30 work again.
		Adding "power off" capability to the RTC, as used on IP32
		(and possibly IP30 and others).
		Some IP30 updates.
20050117	Debugger updates (symbolic register names instead of just rX,
		and using %08x instead of %016llx when emulating 32-bit CPUs
		in more places than before).
		Removing the dummy sgi_nasid and sgi_cpuinfo devices.
		Also using symbolic names for coprocessor 0 registers.
		Adding DEV_MP_MEMORY to dev_mp.c.
		Adding a 'put' command to the debugger.
		ARCBIOS function 0x100 used by IRIX seems to _NOT_ be a
		ReturnFromMain(), but something else undocumented.
		The count and compare registers are now 32-bit in all
		places, as they should be. (This causes, among other things,
		OpenBSD/sgi to not hang randomly in userspace anymore.)
		On breakpoints, the debugger is now entered _at_ the
		instruction at the breakpoint, not after it.
		Some cursor keys now work when inputed via X.
		Refreshing the MC146818 device a bit more.
20050118	Trying to add some support for less-than-4KB virtual pages,
		used by at least VR4131. Thanks to Alexander Yurchenko for
		noticing this. (I'm assuming for now that all R41xx work
		this way, which is not necessarily true.) It doesn't really
		work yet though.
		Renicing the "loading files" messages and other things
		displayed during startup.
		Changing the disassembly output of ori, xori, and andi to
		unsigned hex immediate, instead of decimal (as suggested
		by Alec Voropay).
		configure-script update for HP-UX, and switching from using
		inet_aton() to inet_pton() (as suggested by Nils Weller).
		Also adding -lnsl on Solaris, if required by inet_pton().
		Lots of minor R4100-related updates.
20050119	Correcting the R4100 config register in src/coproc.c, and
		a minor update to dev_vr41xx.
		Finally began a redesign/remodelling/cleanup that I have had
		in mind for quite some time... moving many things that were
		in struct emul into a new struct machine.
		Userland emulation now works with bintrans.
		Refreshing the LANCE controller (dev_le.c).
		Fixing the LK201 keyboard id.
20050120	Continuing on the remodelling/cleanup.
		Fixing the SCSI bug (which was triggered sometimes by
		NetBSD 2.0/pmax on Linux/i386 hosts).
		Adding a speed-limit hack to the mc146818 device when running
		in DECstation mode (limiting to emulated 30 MHz clock, so
		that Ultrix doesn't freak out).
		Adding an ugly workaround for the floating-point bug which
		is triggered when running NetBSD/pmax 2.0 on an Alpha host.
		The count/compare interrupt will not be triggered now, if
		the compare register is left untouched.
		Many, many other fixes...
20050121	Continuing the remodelling/cleanup. (Mostly working on the
		network stack, and on moving towards multiple emulations
		with multiple machines per emulation.)
		Fixbug: not clearing lowest parts of lo0 and hi on tlbr
		(seems to increase performance when emulating Linux?).
20050122	Continuing the remodelling/cleanup.
		Linux on DECstation uses a non-used part of the RTC registers
		for the year value; this is supported now, so Linux thinks
		it is 2005 and not 2000.
		Began hacking on something to reply to Debian's DHCP requests,
		but it's not working yet.
20050123	Continuing the remodelling/cleanup.
20050124	Continuing the remodelling/cleanup.
		Converting the dev_vga charcell memory to support direct
		bintrans access (similar to how dev_fb works), and fixing a
		couple of bintrans bugs in the process.
		The emulator now compiles under OpenBSD/arc 2.3 without
		crashing (mostly due to the bintrans fixes, but also some
		minor updates to the configure script).
20050125	Continuing the remodelling/cleanup.
		The '-a' option was missing in the Hello World example in the
		documentation. (Thanks to Soohyun Cho for noticing this.)
20050126	Continuing the remodelling/cleanup. Moving around stuff in
		the header files, etc. Adding a '-K' command line option, which
		forces the debugger to be entered at the exit of a simulation,
		regardless of failure or success. Beginning to work on the
		config file parser.
		Splitting doc/index.html into experiments.html, guestoses.html,
		intro.html, and misc.html.
		Updating the man page and adding a skeleton section about the
		configure files to doc/misc.html.
20050127	Minor documentation updates.
20050128	Continuing the remodelling/cleanup, mostly working on the
		config file parser (adding a couple of machine words, enough
		to run simple emulations, and adding support for multi-line
		comments using tuborgs).
		Removing some command line options for the least working
		emulation modes (-e, -f, -g, -E, -H), adding new -E and -e
		options for selecting machine type.
		Moving global variables from src/x11.c into struct machine (a
		bit buggy, but it seems to almost work).
20050129	Removing the Playstation 2 mode (-B) and hpcmips modes (-F)
		from the command line as well.
		Changing the -T command line option from meaning "trace on bad
		address" to meaning "enter the single-step debugger on bad
		address".
		More updates to the configuration file parser (nested tuborg
		comments, more options, ...).
		Making -s a global setting, not just affecting one machine.
		Trying to fix the X11 event stuff... but it's so ugly that it
		must be rewritten later.
		Continuing the multi-emul cleanup.
		Bugfixes and other updates to dev_vga.
20050130	Continuing the remodelling/cleanup. Finally moving out the
		MIPS dependant stuff of the cpu struct into its own struct.
		Renaming cpu.c to cpu_mips.c, and cpu_common.c to cpu.c.
		Adding a dummy cpu_ppc.c.
		Removing the UltraSPARC bintrans backend.
		Many other minor updates.
		src/file.c should now be free from MIPS-dependancies.
20050131	Continuing a little bit more on src/file.c. PPC ELFs can now
		be loaded, it seems.
		Continuing on src/cpu_ppc.c.
		'mips' is undefined by the configure script, if it is defined
		by default. (Fixes build on at least OpenBSD/arc and
		NetBSD/arc, where gcc defines 'mips'.)
		A couple of other minor fixes.
		Removing the "Changing framebuffer resolution" section from
		doc/misc.h (because it's buggy and not very useful anway).
		Adding a mystrtoull(), used on systems where there is no
		strtoull() in libc.
		Adding 'add_x11_display' to the configure file parser 
		(corresponding to the -z command line option).
		Continuing the multi-emul machine cleanup.
20050201	Minor updates (man page, RELEASE, README).
		Continuing the cleanup.
		Adding a 'name' field to the emul struct, and adding a command
		to the debugger ("focus") to make it possible to switch focus
		to different machines (in different emuls).
		Beginning to work on the PPC disassembler etc. Hello World
		for linux-ppc64 can be disassembled :-)
20050202	Adding a hack for reading symbols from Microsoft's variant of
		COFF files.
		Adding a dummy cpu_sparc.c and include/cpu_sparc.h.
		Cleaning up more to support multiple cpu families.
		Various other minor updates.
		Fixing another old-gcc-on-Alpha problem.
20050203	Bintrans cache size is now variable, settable by a new
		configuration file option 'bintrans_size'.
		The debugger can now theoretically call disassembler functions
		for cpu families with non-fixed instruction word length.
		Working more on the mec controller. It now works well enough
		to let both NetBSD/sgimips and OpenBSD/sgi connect to the
		outside world using ftp :-)
		Continuing on the cleanup of the networking subsystem.
20050204	Continuing the cleanup.
		Working on a way to use separate xterms for serial ports and
		other console input, when emulating multiple machines (or one
		machine with multiple serial lines active).
20050205	Minor documentation updates.
20050206	Moving console.c from devices/ to src/, and continuing the
		work on using separate windows for each serial console.
		Trying to get OpenBSD/sgi to boot with root-on-nfs on an
		emulated NetBSD/pmax server, but no success in setting up
		the server yet.
20050207	Continuing on the console cleanup.
		Adding a 'start_paused' configuration file option, and a
		'pause' command to the debugger.
20050208	Everything now builds with --withoutmips.
		Continuing on the documentation on how to run OpenBSD/sgi, but
		no actual success yet.
		sizeof => (int)sizeof in the configure script (as suggested by
		Nils Weller).
20050209	Adding a check for -lm to the configure script.
		Continuing on the cleanup: trying to make memory_rw non-MIPS
		dependant.
		Trying to make a better fix for the cdrom-block-size problems
		on FreeBSD. (It now works with a Windows NT 4.0 cdrom in my
		drive.)
		Began a clean-up of the userland subsystem.
20050210	Continuing the userland cleanup.
		IBM's Hello World example for Linux/PPC64 runs fine now.
20050211	Continuing the cleanup. Removing the --userland configure
		option (because support for userland is always included now).
		Working more on getting OpenBSD/sgi to boot with root on
		nfs. (Booting with the ramdisk kernel, and mounting root via
		nfs works, but not yet from the generic kernel.)
		Major update to the manpage.
		Removing the -G command line option (SGI modes).
20050212	Updating the documentation (experimental devices: dev_cons
		and dev_mp, better hello.c, and some other things).
20050213	Some minor fixes: documentation, 80 columns in some source
		files, better configure script options.
		Adding some more PPC instructions.
		Added a NOFPU flag to the MIPS cpu flags, so that executing
		FPU instructions on for example VR4xxx will fail (as suggested
		by Alexander Yurchenko).
20050214	Implementing more PPC instructions.
		Adding dev_pmppc.
20050215	Continuing the work on PPC emulation. Adding a (mostly non-
		working) NetBSD/powerpc userland mode, a (buggy)
		show_trace_tree thing (simliar to the MIPS version).
20050216	Continuing...
20050218	Continuing the clean-up. (Merging the devices and devstate
		debugger commands, more 80-column cleanup, some documentation
		updates, ...).
20050219	Removing the -D, -A, and -a command line options. Updating the
		documentation, in preparation for the next release.
		Adding interrupt stuff to dev_cons.
		Single-stepping now looks/works better with bintrans enabled.
		Beginning the first phase of release testing; various minor
		updates to make everything build cleanly on Solaris.
20050220	Continuing testing for the release...
                
==============  RELEASE 0.3  ==============

20050221	Minor updates. Some more clean-up.
		Beginning on the new device registry stuff.
20050222	Continuing on the device stuff, and doing various other kinds
		of clean-up.
		Adding a dummy BeBox mode.
		Making the pc register common for all cpu families.
		Adding some more PPC instructions and fixing some bugs.
20050223	Continuing on the BeBox stuff, and adding more instructions.
		Adding an ns16550 to the VR4131 emulation (which is probably
		a close enough fake to the VR4131's SIU unit).
20050224	Minor updates. Adding dummy PReP, macppc, and DB64360 modes.
		Continuing on the device registry rewrite.
20050225	Continuing on the device stuff.
20050226	Continuing more on the device rewrite.
		Separating the "testmips" machine into testmips and baremips
		(and similarly with the ppc machine).
		Redesigning the device registry again :-)
		Adding a "device" command to the config file parser.
		Adding "device add" and "device remove" to the debugger.
		Removing pcidevs.h, because it was almost unused.
20050228	Correcting the Sprite disk image url in the documentation.
20050301	Adding an URISC cpu emulation mode (single-opcode machine).
20050303	Adding some files to the experiments directory (rssb_as.c,
		rssb_as.README, urisc_test.s).
		Continuing on the device stuff.
20050304	Minor documentation update. Also, the SPARC, PPC, and URISC
		modes are now enabled by default in the configure script.
		Some minor PPC updates (adding a VGA device to the bebox
		emulation mode).
20050305	Moving the static i386 bintrans runchunk code snippet (and the
		others) to be dynamically generated. (This allows the code to
		compile on i386 with old gcc.)
		Loading PPC64 ELFs now sets R2 to the TOC base.
		Changing the name of the emulator from mips64emul to GXemul.
		Splitting out the configuration file part of the documentation
		into its own file (configfiles.html).
20050306	Some really minor documentation updates.
		Adding a -D command line option (for "fully deterministic"
		behaviour).
20050308	Minor PPC updates. Adding a dummy OpenFirmware emulation layer.
20050309	Adding a hack for systems without inet_pton (such as Cygwin in
		Windows) as suggested by Soohyun Cho. (And updating the
		configure script too.)
		Adding a dummy HPPA cpu family.
		Some more OpenFirmware updates.
		Faster loading of badly aligned ELF regions.
20050311	Minor updates. Adding a dummy "NEC MobilePro 780" hpcmips
		machine mode; disabling direct bintrans access to framebuffers
		that are not 4K page aligned.
20050312	Adding an ugly KIU hack to the VR41xx device (which enables
		NetBSD/hpcmips MobilePro 780 keyboard input).
20050313	Adding a dummy "pcic" device (a pcmcia card controller).
		Adding a dummy Alpha cpu emulation mode.
		Fixing a strcmp length bug (thanks to Alexander Yurchenko for
		noticing the bug).
20050314	Some minor bintrans-related updates in preparation for a new
		bintrans subsystem: command line option -b now means "old
		bintrans", -B means "disable bintrans", and using no option at
		all selects "new bintrans".
		Better generation of MAC addresses when emulating multiple
		machines and/or NICs.
		Minor documentation updates (regarding configuration files).
20050315	Adding dummy standby, suspend, and hibernate MIPS opcodes.
		RTC interrupt hack for VR4121 (hpcmips).
		Enough of the pcic is now emulated to let NetBSD/hpcmips detect
		a PCMCIA harddisk controller card (but there is no support for
		ISA/PCMCIA interrupts yet).
		Adding preliminary instructions on how to install
		NetBSD/hpcmips.
		Continuing the attempt to get harddisks working with interrupts
		(pcic, wdc on hpcmips).
20050318	Minor updates. (Fixing disassembly of MIPS bgtz etc., 
		continuing on the device cleanup, ...)
20050319	Minor updates.
20050320	Minor updates.
20050322	Various minor updates.
20050323	Some more minor updates.
20050328	VR41xx-related updates (keyboard stuff: the space key and
		shifted and ctrled keys are now working in userland (ie
		NetBSD/hpcmips' ramdisk installer).
		Also adding simple cursor key support to the VR41xx kiu.
20050329	Some progress on the wdc.
		Updating the documentation of how to (possibly) install
		NetBSD/hpcmips, once it is working.
		Adding delays before wdc interrupts; this allows NetBSD
		2.0/hpcmips to be successfully installed!
		Mirroring physical addresses 0x8....... to 0x00000000 on
		hpcmips; this makes it possible to run X11 inside
		NetBSD/hpcmips :-)
		Updating the documentation regarding NetBSD/hpcmips.
		Fixing 16-bit vs 15-bit color in dev_fb.
20050330	Print a warning when the user attempts to load a gzipped
		file. (Thanks to Juan RP for making me aware of this "bug".)
20050331	Importing aic7xxx_reg.h from NetBSD.
		Adding a "-x" command line option, which forces xterms for
		each emulated serial port to always be opened.
		Adding a MobilePro 770 mode (same as 780, but different
		framebuffer address which allows bintrans = fast scrolling),
		and a MobilePro 800 (with 800x600 pixels framebuffer :-).
20050401	Minor updates.
20050402	Minor updates. (The standby and suspend instructions are
		bintransed as NOPs, and some minor documentation updates.)
20050403	Adding an Agenda VR3 mode, and playing around with a Linux
		kernel image, but not much success yet.
		Changing BIFB_D16_FFFF -> BIFB_D16_0000 for the hpcmips 
		framebuffers, causing NetBSD to boot with correct colors.
		New syntax for loading raw files: loadaddr:skiplen:
		initialpc:filename. (This is necessary to boot the Linux VR3
		kernels.)
		The Linux VR3 kernel boots in both serial console mode and
		using the framebuffer, but it panics relatively early.
20050404	Continuing on the AHC, and some other minor updates.
20050405	Adding a note in doc/experimental.html about "root1.2.6.cramfs"
		(thanks to Alec Voropay for noticing that it wasn't part
		of root1.2.6.kernel-8.00).
		Also adding a note about another cramfs image.
		-o options are now added to the command line passed to the
		Linux kernel, when emulating the VR3.
		Adding a MobilePro 880 mode, and a dummy IBM WorkPad Z50 mode.
20050406	Connecting the VR3 serial controller to irq 9 (Linux calls this
		irq 17), and some other interrupt-related cleanups.
		Reducing the memory overhead per bintranslated page. (Hopefully
		this makes things faster, or at least not slower...)
20050407	Some more cleanup regarding command line argument passing for
		the hpcmips modes.
		Playing with Linux kernels for MobilePro 770 and 800; they get
		as far as mounting a root filesystem, but then crash.
		Doing some testing for the next release.

==============  RELEASE 0.3.1  ==============


1 dpavlin 2 /*
2     * Copyright (C) 2003-2005 Anders Gavare. All rights reserved.
3     *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28     * $Id: cpu_mips.c,v 1.34 2005/03/20 20:27:26 debug Exp $
29     *
30     * MIPS core CPU emulation.
31     */
32    
33     #include <stdio.h>
34     #include <stdlib.h>
35     #include <string.h>
36     #include <sys/types.h>
37     #include <sys/time.h>
38     #include <sys/resource.h>
39     #include <ctype.h>
40    
41     #include "../config.h"
42    
43    
44     #ifndef ENABLE_MIPS
45    
46    
47     #include "cpu_mips.h"
48    
49     /*
50     * mips_cpu_family_init():
51     *
52     * Bogus function.
53     */
54     int mips_cpu_family_init(struct cpu_family *fp)
55     {
56     return 0;
57     }
58    
59    
60     /* TODO: Maybe it isn't very nice to have these global like this... */
61     void mips_cpu_exception(struct cpu *cpu, int exccode, int tlb, uint64_t vaddr,
62     int coproc_nr, uint64_t vaddr_vpn2, int vaddr_asid, int x_64) { }
63    
64    
65     #else /* ENABLE_MIPS */
66    
67    
68     #include "arcbios.h"
69     #include "bintrans.h"
70     #include "cop0.h"
71     #include "cpu.h"
72     #include "cpu_mips.h"
73     #include "debugger.h"
74     #include "devices.h"
75     #include "emul.h"
76     #include "machine.h"
77     #include "memory.h"
78     #include "mips_cpu_types.h"
79     #include "opcodes_mips.h"
80     #include "symbol.h"
81    
82    
83     extern volatile int single_step;
84     extern int show_opcode_statistics;
85     extern int old_show_trace_tree;
86     extern int old_instruction_trace;
87     extern int old_quiet_mode;
88     extern int quiet_mode;
89    
90     static char *exception_names[] = EXCEPTION_NAMES;
91    
92     static char *hi6_names[] = HI6_NAMES;
93     static char *regimm_names[] = REGIMM_NAMES;
94     static char *special_names[] = SPECIAL_NAMES;
95     static char *special2_names[] = SPECIAL2_NAMES;
96    
97     static char *regnames[] = MIPS_REGISTER_NAMES;
98     static char *cop0_names[] = COP0_NAMES;
99    
100    
101     #include "cpu_mips16.c"
102    
103    
104     /*
105     * regname():
106     *
107     * Convert a register number into either 'r0', 'r31' etc, or a symbolic
108     * name, depending on machine->show_symbolic_register_names.
109     *
110     * NOTE: _NOT_ reentrant.
111     */
112     static char *regname(struct machine *machine, int r)
113     {
114     static char ch[4];
115     ch[3] = ch[2] = '\0';
116    
117     if (r<0 || r>=32)
118     strcpy(ch, "xx");
119     else if (machine->show_symbolic_register_names)
120     strcpy(ch, regnames[r]);
121     else
122     sprintf(ch, "r%i", r);
123    
124     return ch;
125     }
126    
127    
128     /*
129     * mips_cpu_new():
130     *
131     * Create a new MIPS cpu object.
132     */
133     struct cpu *mips_cpu_new(struct memory *mem, struct machine *machine,
134     int cpu_id, char *cpu_type_name)
135     {
136     struct cpu *cpu;
137     int i, found, j, tags_size, n_cache_lines, size_per_cache_line;
138     struct mips_cpu_type_def cpu_type_defs[] = MIPS_CPU_TYPE_DEFS;
139     int64_t secondary_cache_size;
140     int x, linesize;
141    
142     /* Scan the cpu_type_defs list for this cpu type: */
143     i = 0;
144     found = -1;
145     while (i >= 0 && cpu_type_defs[i].name != NULL) {
146     if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
147     found = i;
148     break;
149     }
150     i++;
151     }
152    
153     if (found == -1)
154     return NULL;
155    
156     cpu = malloc(sizeof(struct cpu));
157     if (cpu == NULL) {
158     fprintf(stderr, "out of memory\n");
159     exit(1);
160     }
161    
162     memset(cpu, 0, sizeof(struct cpu));
163     cpu->memory_rw = mips_memory_rw;
164     cpu->cd.mips.cpu_type = cpu_type_defs[found];
165     cpu->name = cpu->cd.mips.cpu_type.name;
166     cpu->mem = mem;
167     cpu->machine = machine;
168     cpu->cpu_id = cpu_id;
169     cpu->byte_order = EMUL_LITTLE_ENDIAN;
170     cpu->bootstrap_cpu_flag = 0;
171     cpu->running = 0;
172     cpu->cd.mips.gpr[MIPS_GPR_SP] = INITIAL_STACK_POINTER;
173    
174     if (cpu_id == 0)
175     debug("%s", cpu->cd.mips.cpu_type.name);
176    
177     /*
178     * CACHES:
179     *
180     * 1) Use DEFAULT_PCACHE_SIZE and DEFAULT_PCACHE_LINESIZE etc.
181     * 2) If there are specific values defined for this type of cpu,
182     * in its cpu_type substruct, then let's use those.
183     * 3) Values in the emul struct override both of the above.
184     *
185     * Once we've decided which values to use, they are stored in
186     * the emul struct so they can be used from src/machine.c etc.
187     */
188    
189     x = DEFAULT_PCACHE_SIZE;
190     if (cpu->cd.mips.cpu_type.default_pdcache)
191     x = cpu->cd.mips.cpu_type.default_pdcache;
192     if (machine->cache_pdcache == 0)
193     machine->cache_pdcache = x;
194    
195     x = DEFAULT_PCACHE_SIZE;
196     if (cpu->cd.mips.cpu_type.default_picache)
197     x = cpu->cd.mips.cpu_type.default_picache;
198     if (machine->cache_picache == 0)
199     machine->cache_picache = x;
200    
201     if (machine->cache_secondary == 0)
202     machine->cache_secondary = cpu->cd.mips.cpu_type.default_scache;
203    
204     linesize = DEFAULT_PCACHE_LINESIZE;
205     if (cpu->cd.mips.cpu_type.default_pdlinesize)
206     linesize = cpu->cd.mips.cpu_type.default_pdlinesize;
207     if (machine->cache_pdcache_linesize == 0)
208     machine->cache_pdcache_linesize = linesize;
209    
210     linesize = DEFAULT_PCACHE_LINESIZE;
211     if (cpu->cd.mips.cpu_type.default_pilinesize)
212     linesize = cpu->cd.mips.cpu_type.default_pilinesize;
213     if (machine->cache_picache_linesize == 0)
214     machine->cache_picache_linesize = linesize;
215    
216     linesize = 0;
217     if (cpu->cd.mips.cpu_type.default_slinesize)
218     linesize = cpu->cd.mips.cpu_type.default_slinesize;
219     if (machine->cache_secondary_linesize == 0)
220     machine->cache_secondary_linesize = linesize;
221    
222    
223     /*
224     * Primary Data and Instruction caches:
225     */
226     for (i=CACHE_DATA; i<=CACHE_INSTRUCTION; i++) {
227     switch (i) {
228     case CACHE_DATA:
229     x = 1 << machine->cache_pdcache;
230     linesize = 1 << machine->cache_pdcache_linesize;
231     break;
232     case CACHE_INSTRUCTION:
233     x = 1 << machine->cache_picache;
234     linesize = 1 << machine->cache_picache_linesize;
235     break;
236     }
237    
238     /* Primary cache size and linesize: */
239     cpu->cd.mips.cache_size[i] = x;
240     cpu->cd.mips.cache_linesize[i] = linesize;
241    
242     switch (cpu->cd.mips.cpu_type.rev) {
243     case MIPS_R2000:
244     case MIPS_R3000:
245     size_per_cache_line = sizeof(struct r3000_cache_line);
246     break;
247     default:
248     size_per_cache_line = sizeof(struct r4000_cache_line);
249     }
250    
251     cpu->cd.mips.cache_mask[i] = cpu->cd.mips.cache_size[i] - 1;
252     cpu->cd.mips.cache_miss_penalty[i] = 10; /* TODO ? */
253    
254     cpu->cd.mips.cache[i] = malloc(cpu->cd.mips.cache_size[i]);
255     if (cpu->cd.mips.cache[i] == NULL) {
256     fprintf(stderr, "out of memory\n");
257     }
258    
259     n_cache_lines = cpu->cd.mips.cache_size[i] /
260     cpu->cd.mips.cache_linesize[i];
261     tags_size = n_cache_lines * size_per_cache_line;
262    
263     cpu->cd.mips.cache_tags[i] = malloc(tags_size);
264     if (cpu->cd.mips.cache_tags[i] == NULL) {
265     fprintf(stderr, "out of memory\n");
266     }
267    
268     /* Initialize the cache tags: */
269     switch (cpu->cd.mips.cpu_type.rev) {
270     case MIPS_R2000:
271     case MIPS_R3000:
272     for (j=0; j<n_cache_lines; j++) {
273     struct r3000_cache_line *rp;
274     rp = (struct r3000_cache_line *)
275     cpu->cd.mips.cache_tags[i];
276     rp[j].tag_paddr = 0;
277     rp[j].tag_valid = 0;
278     }
279     break;
280     default:
281     ;
282     }
283    
284     /* Set cache_last_paddr to something "impossible": */
285     cpu->cd.mips.cache_last_paddr[i] = IMPOSSIBLE_PADDR;
286     }
287    
288     /*
289     * Secondary cache:
290     */
291     secondary_cache_size = 0;
292     if (machine->cache_secondary)
293     secondary_cache_size = 1 << machine->cache_secondary;
294     /* TODO: linesize... */
295    
296     if (cpu_id == 0) {
297     debug(" (I+D = %i+%i KB",
298     (int)(cpu->cd.mips.cache_size[CACHE_INSTRUCTION] / 1024),
299     (int)(cpu->cd.mips.cache_size[CACHE_DATA] / 1024));
300    
301     if (secondary_cache_size != 0) {
302     debug(", L2 = ");
303     if (secondary_cache_size >= 1048576)
304     debug("%i MB", (int)
305     (secondary_cache_size / 1048576));
306     else
307     debug("%i KB", (int)
308     (secondary_cache_size / 1024));
309     }
310    
311     debug(")");
312     }
313    
314     /* System coprocessor (0), and FPU (1): */
315     cpu->cd.mips.coproc[0] = mips_coproc_new(cpu, 0);
316     cpu->cd.mips.coproc[1] = mips_coproc_new(cpu, 1);
317    
318     /*
319     * Initialize the cpu->cd.mips.pc_last_* cache (a 1-entry cache of the
320     * last program counter value). For pc_last_virtual_page, any
321     * "impossible" value will do. The pc should never ever get this
322     * value. (The other pc_last* variables do not need initialization,
323     * as they are not used before pc_last_virtual_page.)
324     */
325     cpu->cd.mips.pc_last_virtual_page = PC_LAST_PAGE_IMPOSSIBLE_VALUE;
326    
327     switch (cpu->cd.mips.cpu_type.mmu_model) {
328     case MMU3K:
329     cpu->translate_address = translate_address_mmu3k;
330     break;
331     case MMU8K:
332     cpu->translate_address = translate_address_mmu8k;
333     break;
334     case MMU10K:
335     cpu->translate_address = translate_address_mmu10k;
336     break;
337     default:
338     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
339     cpu->translate_address = translate_address_mmu4100;
340     else
341     cpu->translate_address = translate_address_generic;
342     }
343    
344     return cpu;
345     }
346    
347    
348     /*
349     * mips_cpu_show_full_statistics():
350     *
351     * Show detailed statistics on opcode usage on each cpu.
352     */
353     void mips_cpu_show_full_statistics(struct machine *m)
354     {
355     int i, s1, s2, iadd = 4;
356    
357     if (m->bintrans_enable)
358     fatal("NOTE: Dynamic binary translation is used; this list"
359     " of opcode usage\n only includes instructions that"
360     " were interpreted manually!\n");
361    
362     for (i=0; i<m->ncpus; i++) {
363     fatal("cpu%i opcode statistics:\n", i);
364     debug_indentation(iadd);
365    
366     for (s1=0; s1<N_HI6; s1++) {
367     if (m->cpus[i]->cd.mips.stats_opcode[s1] > 0)
368     fatal("opcode %02x (%7s): %li\n", s1,
369     hi6_names[s1],
370     m->cpus[i]->cd.mips.stats_opcode[s1]);
371    
372     debug_indentation(iadd);
373     if (s1 == HI6_SPECIAL)
374     for (s2=0; s2<N_SPECIAL; s2++)
375     if (m->cpus[i]->cd.mips.stats__special[
376     s2] > 0)
377     fatal("special %02x (%7s): "
378     "%li\n", s2, special_names[
379     s2], m->cpus[i]->cd.mips.
380     stats__special[s2]);
381     if (s1 == HI6_REGIMM)
382     for (s2=0; s2<N_REGIMM; s2++)
383     if (m->cpus[i]->cd.mips.stats__regimm[
384     s2] > 0)
385     fatal("regimm %02x (%7s): "
386     "%li\n", s2, regimm_names[
387     s2], m->cpus[i]->cd.mips.
388     stats__regimm[s2]);
389     if (s1 == HI6_SPECIAL2)
390     for (s2=0; s2<N_SPECIAL; s2++)
391     if (m->cpus[i]->cd.mips.stats__special2
392     [s2] > 0)
393     fatal("special2 %02x (%7s): "
394     "%li\n", s2,
395     special2_names[s2], m->
396     cpus[i]->cd.mips.
397     stats__special2[s2]);
398     debug_indentation(-iadd);
399     }
400    
401     debug_indentation(-iadd);
402     }
403     }
404    
405    
406     /*
407     * mips_cpu_tlbdump():
408     *
409     * Called from the debugger to dump the TLB in a readable format.
410     * x is the cpu number to dump, or -1 to dump all CPUs.
411     *
412     * If rawflag is nonzero, then the TLB contents isn't formated nicely,
413     * just dumped.
414     */
415     void mips_cpu_tlbdump(struct machine *m, int x, int rawflag)
416     {
417     int i, j;
418    
419     /* Nicely formatted output: */
420     if (!rawflag) {
421     for (i=0; i<m->ncpus; i++) {
422     int pageshift = 12;
423    
424     if (x >= 0 && i != x)
425     continue;
426    
427     if (m->cpus[i]->cd.mips.cpu_type.rev == MIPS_R4100)
428     pageshift = 10;
429    
430     /* Print index, random, and wired: */
431     printf("cpu%i: (", i);
432     switch (m->cpus[i]->cd.mips.cpu_type.isa_level) {
433     case 1:
434     case 2:
435     printf("index=0x%x random=0x%x",
436     (int) ((m->cpus[i]->cd.mips.coproc[0]->
437     reg[COP0_INDEX] & R2K3K_INDEX_MASK)
438     >> R2K3K_INDEX_SHIFT),
439     (int) ((m->cpus[i]->cd.mips.coproc[0]->
440     reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
441     >> R2K3K_RANDOM_SHIFT));
442     break;
443     default:
444     printf("index=0x%x random=0x%x",
445     (int) (m->cpus[i]->cd.mips.coproc[0]->
446     reg[COP0_INDEX] & INDEX_MASK),
447     (int) (m->cpus[i]->cd.mips.coproc[0]->
448     reg[COP0_RANDOM] & RANDOM_MASK));
449     printf(" wired=0x%llx", (long long)
450     m->cpus[i]->cd.mips.coproc[0]->
451     reg[COP0_WIRED]);
452     }
453    
454     printf(")\n");
455    
456     for (j=0; j<m->cpus[i]->cd.mips.cpu_type.
457     nr_of_tlb_entries; j++) {
458     uint64_t hi,lo0,lo1,mask;
459     hi = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi;
460     lo0 = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0;
461     lo1 = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1;
462     mask = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask;
463    
464     printf("%3i: ", j);
465     switch (m->cpus[i]->cd.mips.cpu_type.mmu_model) {
466     case MMU3K:
467     if (!(lo0 & R2K3K_ENTRYLO_V)) {
468     printf("(invalid)\n");
469     continue;
470     }
471     printf("vaddr=0x%08x ",
472     (int) (hi&R2K3K_ENTRYHI_VPN_MASK));
473     if (lo0 & R2K3K_ENTRYLO_G)
474     printf("(global), ");
475     else
476     printf("(asid %02x),",
477     (int) ((hi & R2K3K_ENTRYHI_ASID_MASK)
478     >> R2K3K_ENTRYHI_ASID_SHIFT));
479     printf(" paddr=0x%08x ",
480     (int) (lo0&R2K3K_ENTRYLO_PFN_MASK));
481     if (lo0 & R2K3K_ENTRYLO_N)
482     printf("N");
483     if (lo0 & R2K3K_ENTRYLO_D)
484     printf("D");
485     printf("\n");
486     break;
487     default:
488     /* TODO: MIPS32 doesn't need 0x16llx */
489     if (m->cpus[i]->cd.mips.cpu_type.mmu_model == MMU10K)
490     printf("vaddr=0x%1x..%011llx ",
491     (int) (hi >> 60),
492     (long long) (hi&ENTRYHI_VPN2_MASK_R10K));
493     else
494     printf("vaddr=0x%1x..%010llx ",
495     (int) (hi >> 60),
496     (long long) (hi&ENTRYHI_VPN2_MASK));
497     if (hi & TLB_G)
498     printf("(global): ");
499     else
500     printf("(asid %02x):",
501     (int) (hi & ENTRYHI_ASID));
502    
503     /* TODO: Coherency bits */
504    
505     if (!(lo0 & ENTRYLO_V))
506     printf(" p0=(invalid) ");
507     else
508     printf(" p0=0x%09llx ", (long long)
509     (((lo0&ENTRYLO_PFN_MASK) >> ENTRYLO_PFN_SHIFT) << pageshift));
510     printf(lo0 & ENTRYLO_D? "D" : " ");
511    
512     if (!(lo1 & ENTRYLO_V))
513     printf(" p1=(invalid) ");
514     else
515     printf(" p1=0x%09llx ", (long long)
516     (((lo1&ENTRYLO_PFN_MASK) >> ENTRYLO_PFN_SHIFT) << pageshift));
517     printf(lo1 & ENTRYLO_D? "D" : " ");
518     mask |= (1 << (pageshift+1)) - 1;
519     switch (mask) {
520     case 0x7ff: printf(" (1KB)"); break;
521     case 0x1fff: printf(" (4KB)"); break;
522     case 0x7fff: printf(" (16KB)"); break;
523     case 0x1ffff: printf(" (64KB)"); break;
524     case 0x7ffff: printf(" (256KB)"); break;
525     case 0x1fffff: printf(" (1MB)"); break;
526     case 0x7fffff: printf(" (4MB)"); break;
527     case 0x1ffffff: printf(" (16MB)"); break;
528     case 0x7ffffff: printf(" (64MB)"); break;
529     default:
530     printf(" (mask=%08x?)", (int)mask);
531     }
532     printf("\n");
533     }
534     }
535     }
536    
537     return;
538     }
539    
540     /* Raw output: */
541     for (i=0; i<m->ncpus; i++) {
542     if (x >= 0 && i != x)
543     continue;
544    
545     /* Print index, random, and wired: */
546     printf("cpu%i: (", i);
547    
548     if (m->cpus[i]->cd.mips.cpu_type.isa_level < 3 ||
549     m->cpus[i]->cd.mips.cpu_type.isa_level == 32)
550     printf("index=0x%08x random=0x%08x",
551     (int)m->cpus[i]->cd.mips.coproc[0]->reg[COP0_INDEX],
552     (int)m->cpus[i]->cd.mips.coproc[0]->reg[COP0_RANDOM]);
553     else
554     printf("index=0x%016llx random=0x%016llx", (long long)
555     m->cpus[i]->cd.mips.coproc[0]->reg[COP0_INDEX],
556     (long long)m->cpus[i]->cd.mips.coproc[0]->reg
557     [COP0_RANDOM]);
558    
559     if (m->cpus[i]->cd.mips.cpu_type.isa_level >= 3)
560     printf(" wired=0x%llx", (long long)
561     m->cpus[i]->cd.mips.coproc[0]->reg[COP0_WIRED]);
562    
563     printf(")\n");
564    
565     for (j=0; j<m->cpus[i]->cd.mips.cpu_type.nr_of_tlb_entries; j++) {
566     if (m->cpus[i]->cd.mips.cpu_type.mmu_model == MMU3K)
567     printf("%3i: hi=0x%08x lo=0x%08x\n",
568     j,
569     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,
570     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0);
571     else if (m->cpus[i]->cd.mips.cpu_type.isa_level < 3 ||
572     m->cpus[i]->cd.mips.cpu_type.isa_level == 32)
573     printf("%3i: hi=0x%08x mask=0x%08x "
574     "lo0=0x%08x lo1=0x%08x\n", j,
575     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,
576     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask,
577     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0,
578     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1);
579     else
580     printf("%3i: hi=0x%016llx mask=0x%016llx "
581     "lo0=0x%016llx lo1=0x%016llx\n", j,
582     (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,
583     (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask,
584     (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0,
585     (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1);
586     }
587     }
588     }
589    
590    
591     /*
592     * mips_cpu_register_match():
593     */
594     void mips_cpu_register_match(struct machine *m, char *name,
595     int writeflag, uint64_t *valuep, int *match_register)
596     {
597     int cpunr = 0;
598    
599     /* CPU number: */
600    
601     /* TODO */
602    
603     /* Register name: */
604     if (strcasecmp(name, "pc") == 0) {
605     if (writeflag) {
606     m->cpus[cpunr]->pc = *valuep;
607     if (m->cpus[cpunr]->cd.mips.delay_slot) {
608     printf("NOTE: Clearing the delay slot"
609     " flag! (It was set before.)\n");
610     m->cpus[cpunr]->cd.mips.delay_slot = 0;
611     }
612     if (m->cpus[cpunr]->cd.mips.nullify_next) {
613     printf("NOTE: Clearing the nullify-ne"
614     "xt flag! (It was set before.)\n");
615     m->cpus[cpunr]->cd.mips.nullify_next = 0;
616     }
617     } else
618     *valuep = m->cpus[cpunr]->pc;
619     *match_register = 1;
620     } else if (strcasecmp(name, "hi") == 0) {
621     if (writeflag)
622     m->cpus[cpunr]->cd.mips.hi = *valuep;
623     else
624     *valuep = m->cpus[cpunr]->cd.mips.hi;
625     *match_register = 1;
626     } else if (strcasecmp(name, "lo") == 0) {
627     if (writeflag)
628     m->cpus[cpunr]->cd.mips.lo = *valuep;
629     else
630     *valuep = m->cpus[cpunr]->cd.mips.lo;
631     *match_register = 1;
632     } else if (name[0] == 'r' && isdigit((int)name[1])) {
633     int nr = atoi(name + 1);
634     if (nr >= 0 && nr < N_MIPS_GPRS) {
635     if (writeflag) {
636     if (nr != 0)
637     m->cpus[cpunr]->cd.mips.gpr[nr] = *valuep;
638     else
639     printf("WARNING: Attempt to modify r0.\n");
640     } else
641     *valuep = m->cpus[cpunr]->cd.mips.gpr[nr];
642     *match_register = 1;
643     }
644     } else {
645     /* Check for a symbolic name such as "t6" or "at": */
646     int nr;
647     for (nr=0; nr<N_MIPS_GPRS; nr++)
648     if (strcmp(name, regnames[nr]) == 0) {
649     if (writeflag) {
650     if (nr != 0)
651     m->cpus[cpunr]->cd.mips.gpr[nr] = *valuep;
652     else
653     printf("WARNING: Attempt to modify r0.\n");
654     } else
655     *valuep = m->cpus[cpunr]->cd.mips.gpr[nr];
656     *match_register = 1;
657     }
658     }
659    
660     if (!(*match_register)) {
661     /* Check for a symbolic coproc0 name: */
662     int nr;
663     for (nr=0; nr<32; nr++)
664     if (strcmp(name, cop0_names[nr]) == 0) {
665     if (writeflag) {
666     coproc_register_write(m->cpus[cpunr],
667     m->cpus[cpunr]->cd.mips.coproc[0], nr,
668     valuep, 1);
669     } else {
670     /* TODO: Use coproc_register_read instead? */
671     *valuep = m->cpus[cpunr]->cd.mips.coproc[0]->reg[nr];
672     }
673     *match_register = 1;
674     }
675     }
676    
677     /* TODO: Coprocessor 1,2,3 registers. */
678     }
679    
680    
681     /*
682     * cpu_flags():
683     *
684     * Returns a pointer to a string containing "(d)" "(j)" "(dj)" or "",
685     * depending on the cpu's current delay_slot and last_was_jumptoself
686     * flags.
687     */
688     static const char *cpu_flags(struct cpu *cpu)
689     {
690     if (cpu->cd.mips.delay_slot) {
691     if (cpu->cd.mips.last_was_jumptoself)
692     return " (dj)";
693     else
694     return " (d)";
695     } else {
696     if (cpu->cd.mips.last_was_jumptoself)
697     return " (j)";
698     else
699     return "";
700     }
701     }
702    
703    
704     /*
705     * mips_cpu_disassemble_instr():
706     *
707     * Convert an instruction word into human readable format, for instruction
708     * tracing.
709     *
710     * If running is 1, cpu->pc should be the address of the instruction.
711     *
712     * If running is 0, things that depend on the runtime environment (eg.
713     * register contents) will not be shown, and addr will be used instead of
714     * cpu->pc for relative addresses.
715     *
716     * NOTE 2: coprocessor instructions are not decoded nicely yet (TODO)
717     */
718     int mips_cpu_disassemble_instr(struct cpu *cpu, unsigned char *originstr,
719     int running, uint64_t dumpaddr, int bintrans)
720     {
721     int hi6, special6, regimm5;
722     int rt, rd, rs, sa, imm, copz, cache_op, which_cache, showtag;
723     uint64_t addr, offset;
724     uint32_t instrword;
725     unsigned char instr[4];
726     char *symbol;
727    
728     if (running)
729     dumpaddr = cpu->pc;
730    
731     symbol = get_symbol_name(&cpu->machine->symbol_context,
732     dumpaddr, &offset);
733     if (symbol != NULL && offset==0)
734     debug("<%s>\n", symbol);
735    
736     if (cpu->machine->ncpus > 1 && running)
737     debug("cpu%i: ", cpu->cpu_id);
738    
739     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
740     cpu->cd.mips.cpu_type.isa_level == 32)
741     debug("%08x", (int)dumpaddr);
742     else
743     debug("%016llx", (long long)dumpaddr);
744    
745     *((uint32_t *)&instr[0]) = *((uint32_t *)&originstr[0]);
746    
747     /*
748     * The rest of the code is written for little endian,
749     * so swap if necessary:
750     */
751     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
752     int tmp = instr[0]; instr[0] = instr[3];
753     instr[3] = tmp;
754     tmp = instr[1]; instr[1] = instr[2];
755     instr[2] = tmp;
756     }
757    
758     debug(": %02x%02x%02x%02x",
759     instr[3], instr[2], instr[1], instr[0]);
760    
761     if (running)
762     debug("%s", cpu_flags(cpu));
763    
764     debug("\t");
765    
766     if (bintrans && running) {
767     debug("(bintrans)");
768     goto disasm_ret;
769     }
770    
771     /*
772     * Decode the instruction:
773     */
774    
775     if (cpu->cd.mips.nullify_next && running) {
776     debug("(nullified)");
777     goto disasm_ret;
778     }
779    
780     hi6 = (instr[3] >> 2) & 0x3f;
781    
782     switch (hi6) {
783     case HI6_SPECIAL:
784     special6 = instr[0] & 0x3f;
785     switch (special6) {
786     case SPECIAL_SLL:
787     case SPECIAL_SRL:
788     case SPECIAL_SRA:
789     case SPECIAL_DSLL:
790     case SPECIAL_DSRL:
791     case SPECIAL_DSRA:
792     case SPECIAL_DSLL32:
793     case SPECIAL_DSRL32:
794     case SPECIAL_DSRA32:
795     rt = instr[2] & 31;
796     rd = (instr[1] >> 3) & 31;
797     sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
798    
799     if (rd == 0 && special6 == SPECIAL_SLL) {
800     if (sa == 0)
801     debug("nop");
802     else if (sa == 1)
803     debug("ssnop");
804     else
805     debug("nop (weird, sa=%i)", sa);
806     goto disasm_ret;
807     } else
808     debug("%s\t%s,",
809     special_names[special6],
810     regname(cpu->machine, rd));
811     debug("%s,%i", regname(cpu->machine, rt), sa);
812     break;
813     case SPECIAL_DSRLV:
814     case SPECIAL_DSRAV:
815     case SPECIAL_DSLLV:
816     case SPECIAL_SLLV:
817     case SPECIAL_SRAV:
818     case SPECIAL_SRLV:
819     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
820     rt = instr[2] & 31;
821     rd = (instr[1] >> 3) & 31;
822     debug("%s\t%s",
823     special_names[special6], regname(cpu->machine, rd));
824     debug(",%s", regname(cpu->machine, rt));
825     debug(",%s", regname(cpu->machine, rs));
826     break;
827     case SPECIAL_JR:
828     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
829     symbol = get_symbol_name(&cpu->machine->symbol_context,
830     cpu->cd.mips.gpr[rs], &offset);
831     debug("jr\t%s", regname(cpu->machine, rs));
832     if (running && symbol != NULL)
833     debug("\t<%s>", symbol);
834     break;
835     case SPECIAL_JALR:
836     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
837     rd = (instr[1] >> 3) & 31;
838     symbol = get_symbol_name(&cpu->machine->symbol_context,
839     cpu->cd.mips.gpr[rs], &offset);
840     debug("jalr\t%s", regname(cpu->machine, rd));
841     debug(",%s", regname(cpu->machine, rs));
842     if (running && symbol != NULL)
843     debug("\t<%s>", symbol);
844     break;
845     case SPECIAL_MFHI:
846     case SPECIAL_MFLO:
847     rd = (instr[1] >> 3) & 31;
848     debug("%s\t%s", special_names[special6],
849     regname(cpu->machine, rd));
850     break;
851     case SPECIAL_MTLO:
852     case SPECIAL_MTHI:
853     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
854     debug("%s\t%s", special_names[special6],
855     regname(cpu->machine, rs));
856     break;
857     case SPECIAL_ADD:
858     case SPECIAL_ADDU:
859     case SPECIAL_SUB:
860     case SPECIAL_SUBU:
861     case SPECIAL_AND:
862     case SPECIAL_OR:
863     case SPECIAL_XOR:
864     case SPECIAL_NOR:
865     case SPECIAL_SLT:
866     case SPECIAL_SLTU:
867     case SPECIAL_DADD:
868     case SPECIAL_DADDU:
869     case SPECIAL_DSUB:
870     case SPECIAL_DSUBU:
871     case SPECIAL_MOVZ:
872     case SPECIAL_MOVN:
873     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
874     rt = instr[2] & 31;
875     rd = (instr[1] >> 3) & 31;
876     if ((special6 == SPECIAL_ADDU ||
877     special6 == SPECIAL_DADDU ||
878     special6 == SPECIAL_SUBU ||
879     special6 == SPECIAL_DSUBU) && rt == 0) {
880     /* Special case 1: addu/daddu/subu/dsubu with
881     rt = the zero register ==> move */
882     debug("move\t%s", regname(cpu->machine, rd));
883     debug(",%s", regname(cpu->machine, rs));
884     } else if ((special6 == SPECIAL_ADDU ||
885     special6 == SPECIAL_DADDU) && rs == 0) {
886     /* Special case 2: addu/daddu with
887     rs = the zero register ==> move */
888     debug("move\t%s", regname(cpu->machine, rd));
889     debug(",%s", regname(cpu->machine, rt));
890     } else {
891     debug("%s\t%s", special_names[special6],
892     regname(cpu->machine, rd));
893     debug(",%s", regname(cpu->machine, rs));
894     debug(",%s", regname(cpu->machine, rt));
895     }
896     break;
897     case SPECIAL_MULT:
898     case SPECIAL_MULTU:
899     case SPECIAL_DMULT:
900     case SPECIAL_DMULTU:
901     case SPECIAL_DIV:
902     case SPECIAL_DIVU:
903     case SPECIAL_DDIV:
904     case SPECIAL_DDIVU:
905     case SPECIAL_TGE:
906     case SPECIAL_TGEU:
907     case SPECIAL_TLT:
908     case SPECIAL_TLTU:
909     case SPECIAL_TEQ:
910     case SPECIAL_TNE:
911     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
912     rt = instr[2] & 31;
913     rd = (instr[1] >> 3) & 31;
914     if (special6 == SPECIAL_MULT) {
915     if (rd != 0) {
916     debug("mult_xx\t%s",
917     regname(cpu->machine, rd));
918     debug(",%s", regname(cpu->machine, rs));
919     debug(",%s", regname(cpu->machine, rt));
920     goto disasm_ret;
921     }
922     }
923     debug("%s\t%s", special_names[special6],
924     regname(cpu->machine, rs));
925     debug(",%s", regname(cpu->machine, rt));
926     break;
927     case SPECIAL_SYNC:
928     imm = ((instr[1] & 7) << 2) + (instr[0] >> 6);
929     debug("sync\t0x%02x", imm);
930     break;
931     case SPECIAL_SYSCALL:
932     imm = (((instr[3] << 24) + (instr[2] << 16) +
933     (instr[1] << 8) + instr[0]) >> 6) & 0xfffff;
934     if (imm != 0)
935     debug("syscall\t0x%05x", imm);
936     else
937     debug("syscall");
938     break;
939     case SPECIAL_BREAK:
940     /* TODO: imm, as in 'syscall'? */
941     debug("break");
942     break;
943     case SPECIAL_MFSA:
944     rd = (instr[1] >> 3) & 31;
945     debug("mfsa\t%s", regname(cpu->machine, rd));
946     break;
947     case SPECIAL_MTSA:
948     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
949     debug("mtsa\t%s", regname(cpu->machine, rs));
950     break;
951     default:
952     debug("unimplemented special6 = 0x%02x", special6);
953     }
954     break;
955     case HI6_BEQ:
956     case HI6_BEQL:
957     case HI6_BNE:
958     case HI6_BNEL:
959     case HI6_BGTZ:
960     case HI6_BGTZL:
961     case HI6_BLEZ:
962     case HI6_BLEZL:
963     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
964     rt = instr[2] & 31;
965     imm = (instr[1] << 8) + instr[0];
966     if (imm >= 32768)
967     imm -= 65536;
968     addr = (dumpaddr + 4) + (imm << 2);
969     debug("%s\t", hi6_names[hi6]);
970    
971     switch (hi6) {
972     case HI6_BEQ:
973     case HI6_BEQL:
974     case HI6_BNE:
975     case HI6_BNEL:
976     debug("%s,", regname(cpu->machine, rt));
977     }
978    
979     debug("%s,", regname(cpu->machine, rs));
980    
981     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
982     cpu->cd.mips.cpu_type.isa_level == 32)
983     debug("0x%08x", (int)addr);
984     else
985     debug("0x%016llx", (long long)addr);
986    
987     symbol = get_symbol_name(&cpu->machine->symbol_context,
988     addr, &offset);
989     if (symbol != NULL && offset != addr)
990     debug("\t<%s>", symbol);
991     break;
992     case HI6_ADDI:
993     case HI6_ADDIU:
994     case HI6_DADDI:
995     case HI6_DADDIU:
996     case HI6_SLTI:
997     case HI6_SLTIU:
998     case HI6_ANDI:
999     case HI6_ORI:
1000     case HI6_XORI:
1001     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1002     rt = instr[2] & 31;
1003     imm = (instr[1] << 8) + instr[0];
1004     if (imm >= 32768)
1005     imm -= 65536;
1006     debug("%s\t%s,", hi6_names[hi6], regname(cpu->machine, rt));
1007     debug("%s,", regname(cpu->machine, rs));
1008     if (hi6 == HI6_ANDI || hi6 == HI6_ORI || hi6 == HI6_XORI)
1009     debug("0x%04x", imm & 0xffff);
1010     else
1011     debug("%i", imm);
1012     break;
1013     case HI6_LUI:
1014     rt = instr[2] & 31;
1015     imm = (instr[1] << 8) + instr[0];
1016     debug("lui\t%s,0x%x", regname(cpu->machine, rt), imm);
1017     break;
1018     case HI6_LB:
1019     case HI6_LBU:
1020     case HI6_LH:
1021     case HI6_LHU:
1022     case HI6_LW:
1023     case HI6_LWU:
1024     case HI6_LD:
1025     case HI6_LQ_MDMX:
1026     case HI6_LWC1:
1027     case HI6_LWC2:
1028     case HI6_LWC3:
1029     case HI6_LDC1:
1030     case HI6_LDC2:
1031     case HI6_LL:
1032     case HI6_LLD:
1033     case HI6_SB:
1034     case HI6_SH:
1035     case HI6_SW:
1036     case HI6_SD:
1037     case HI6_SQ:
1038     case HI6_SC:
1039     case HI6_SCD:
1040     case HI6_SWC1:
1041     case HI6_SWC2:
1042     case HI6_SWC3:
1043     case HI6_SDC1:
1044     case HI6_SDC2:
1045     case HI6_LWL:
1046     case HI6_LWR:
1047     case HI6_LDL:
1048     case HI6_LDR:
1049     case HI6_SWL:
1050     case HI6_SWR:
1051     case HI6_SDL:
1052     case HI6_SDR:
1053     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1054     rt = instr[2] & 31;
1055     imm = (instr[1] << 8) + instr[0];
1056     if (imm >= 32768)
1057     imm -= 65536;
1058     symbol = get_symbol_name(&cpu->machine->symbol_context,
1059     cpu->cd.mips.gpr[rs] + imm, &offset);
1060    
1061     /* LWC3 is PREF in the newer ISA levels: */
1062     /* TODO: Which ISAs? cpu->cd.mips.cpu_type.isa_level >= 4? */
1063     if (hi6 == HI6_LWC3) {
1064     debug("pref\t0x%x,%i(%s)",
1065     rt, imm, regname(cpu->machine, rs));
1066    
1067     if (running) {
1068     debug("\t[0x%016llx = %s]",
1069     (long long)(cpu->cd.mips.gpr[rs] + imm));
1070     if (symbol != NULL)
1071     debug(" = %s", symbol);
1072     debug("]");
1073     }
1074     goto disasm_ret;
1075     }
1076    
1077     debug("%s\t", hi6_names[hi6]);
1078    
1079     if (hi6 == HI6_SWC1 || hi6 == HI6_SWC2 || hi6 == HI6_SWC3 ||
1080     hi6 == HI6_SDC1 || hi6 == HI6_SDC2 ||
1081     hi6 == HI6_LWC1 || hi6 == HI6_LWC2 || hi6 == HI6_LWC3 ||
1082     hi6 == HI6_LDC1 || hi6 == HI6_LDC2)
1083     debug("r%i", rt);
1084     else
1085     debug("%s", regname(cpu->machine, rt));
1086    
1087     debug(",%i(%s)", imm, regname(cpu->machine, rs));
1088    
1089     if (running) {
1090     debug("\t[");
1091    
1092     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
1093     cpu->cd.mips.cpu_type.isa_level == 32)
1094     debug("0x%08x", (int)(cpu->cd.mips.gpr[rs] + imm));
1095     else
1096     debug("0x%016llx",
1097     (long long)(cpu->cd.mips.gpr[rs] + imm));
1098    
1099     if (symbol != NULL)
1100     debug(" = %s", symbol);
1101    
1102     debug(", data=");
1103     } else
1104     break;
1105     /* NOTE: No break here (if we are running) as it is up
1106     to the caller to print 'data'. */
1107     return sizeof(instrword);
1108     case HI6_J:
1109     case HI6_JAL:
1110     imm = (((instr[3] & 3) << 24) + (instr[2] << 16) +
1111     (instr[1] << 8) + instr[0]) << 2;
1112     addr = (dumpaddr + 4) & ~((1 << 28) - 1);
1113     addr |= imm;
1114     symbol = get_symbol_name(&cpu->machine->symbol_context,
1115     addr, &offset);
1116     debug("%s\t0x", hi6_names[hi6]);
1117     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
1118     cpu->cd.mips.cpu_type.isa_level == 32)
1119     debug("%08x", (int)addr);
1120     else
1121     debug("%016llx", (long long)addr);
1122     if (symbol != NULL)
1123     debug("\t<%s>", symbol);
1124     break;
1125     case HI6_COP0:
1126     case HI6_COP1:
1127     case HI6_COP2:
1128     case HI6_COP3:
1129     imm = (instr[3] << 24) + (instr[2] << 16) +
1130     (instr[1] << 8) + instr[0];
1131     imm &= ((1 << 26) - 1);
1132    
1133     /* Call coproc_function(), but ONLY disassembly, no exec: */
1134     coproc_function(cpu, cpu->cd.mips.coproc[hi6 - HI6_COP0],
1135     hi6 - HI6_COP0, imm, 1, running);
1136     return sizeof(instrword);
1137     case HI6_CACHE:
1138     rt = ((instr[3] & 3) << 3) + (instr[2] >> 5); /* base */
1139     copz = instr[2] & 31;
1140     imm = (instr[1] << 8) + instr[0];
1141     cache_op = copz >> 2;
1142     which_cache = copz & 3;
1143     showtag = 0;
1144     debug("cache\t0x%02x,0x%04x(%s)", copz, imm,
1145     regname(cpu->machine, rt));
1146     if (which_cache==0) debug(" [ primary I-cache");
1147     if (which_cache==1) debug(" [ primary D-cache");
1148     if (which_cache==2) debug(" [ secondary I-cache");
1149     if (which_cache==3) debug(" [ secondary D-cache");
1150     debug(", ");
1151     if (cache_op==0) debug("index invalidate");
1152     if (cache_op==1) debug("index load tag");
1153     if (cache_op==2) debug("index store tag"), showtag=1;
1154     if (cache_op==3) debug("create dirty exclusive");
1155     if (cache_op==4) debug("hit invalidate");
1156     if (cache_op==5) debug("fill OR hit writeback invalidate");
1157     if (cache_op==6) debug("hit writeback");
1158     if (cache_op==7) debug("hit set virtual");
1159     if (running)
1160     debug(", addr 0x%016llx",
1161     (long long)(cpu->cd.mips.gpr[rt] + imm));
1162     if (showtag)
1163     debug(", taghi=%08lx lo=%08lx",
1164     (long)cpu->cd.mips.coproc[0]->reg[COP0_TAGDATA_HI],
1165     (long)cpu->cd.mips.coproc[0]->reg[COP0_TAGDATA_LO]);
1166     debug(" ]");
1167     break;
1168     case HI6_SPECIAL2:
1169     special6 = instr[0] & 0x3f;
1170     instrword = (instr[3] << 24) + (instr[2] << 16) +
1171     (instr[1] << 8) + instr[0];
1172     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1173     rt = instr[2] & 31;
1174     rd = (instr[1] >> 3) & 31;
1175     if ((instrword & 0xfc0007ffULL) == 0x70000000) {
1176     debug("madd\t%s", regname(cpu->machine, rd));
1177     debug(",%s", regname(cpu->machine, rs));
1178     debug(",%s", regname(cpu->machine, rt));
1179     } else if (special6 == SPECIAL2_MUL) {
1180     /* TODO: this is just a guess, I don't have the
1181     docs in front of me */
1182     debug("mul\t%s", regname(cpu->machine, rd));
1183     debug(",%s", regname(cpu->machine, rs));
1184     debug(",%s", regname(cpu->machine, rt));
1185     } else if (special6 == SPECIAL2_CLZ) {
1186     debug("clz\t%s", regname(cpu->machine, rd));
1187     debug(",%s", regname(cpu->machine, rs));
1188     } else if (special6 == SPECIAL2_CLO) {
1189     debug("clo\t%s", regname(cpu->machine, rd));
1190     debug(",%s", regname(cpu->machine, rs));
1191     } else if (special6 == SPECIAL2_DCLZ) {
1192     debug("dclz\t%s", regname(cpu->machine, rd));
1193     debug(",%s", regname(cpu->machine, rs));
1194     } else if (special6 == SPECIAL2_DCLO) {
1195     debug("dclo\t%s", regname(cpu->machine, rd));
1196     debug(",%s", regname(cpu->machine, rs));
1197     } else if ((instrword & 0xffff07ffULL) == 0x70000209
1198     || (instrword & 0xffff07ffULL) == 0x70000249) {
1199     if (instr[0] == 0x49) {
1200     debug("pmflo\t%s", regname(cpu->machine, rd));
1201     debug(" (rs=%s)", regname(cpu->machine, rs));
1202     } else {
1203     debug("pmfhi\t%s", regname(cpu->machine, rd));
1204     debug(" (rs=%s)", regname(cpu->machine, rs));
1205     }
1206     } else if ((instrword & 0xfc1fffff) == 0x70000269
1207     || (instrword & 0xfc1fffff) == 0x70000229) {
1208     if (instr[0] == 0x69) {
1209     debug("pmtlo\t%s", regname(cpu->machine, rs));
1210     } else {
1211     debug("pmthi\t%s", regname(cpu->machine, rs));
1212     }
1213     } else if ((instrword & 0xfc0007ff) == 0x700004a9) {
1214     debug("por\t%s", regname(cpu->machine, rd));
1215     debug(",%s", regname(cpu->machine, rs));
1216     debug(",%s", regname(cpu->machine, rt));
1217     } else if ((instrword & 0xfc0007ff) == 0x70000488) {
1218     debug("pextlw\t%s", regname(cpu->machine, rd));
1219     debug(",%s", regname(cpu->machine, rs));
1220     debug(",%s", regname(cpu->machine, rt));
1221     } else {
1222     debug("unimplemented special2 = 0x%02x", special6);
1223     }
1224     break;
1225     case HI6_REGIMM:
1226     regimm5 = instr[2] & 0x1f;
1227     switch (regimm5) {
1228     case REGIMM_BLTZ:
1229     case REGIMM_BGEZ:
1230     case REGIMM_BLTZL:
1231     case REGIMM_BGEZL:
1232     case REGIMM_BLTZAL:
1233     case REGIMM_BLTZALL:
1234     case REGIMM_BGEZAL:
1235     case REGIMM_BGEZALL:
1236     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1237     imm = (instr[1] << 8) + instr[0];
1238     if (imm >= 32768)
1239     imm -= 65536;
1240    
1241     debug("%s\t%s,", regimm_names[regimm5],
1242     regname(cpu->machine, rs));
1243    
1244     addr = (dumpaddr + 4) + (imm << 2);
1245    
1246     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
1247     cpu->cd.mips.cpu_type.isa_level == 32)
1248     debug("0x%08x", (int)addr);
1249     else
1250     debug("0x%016llx", (long long)addr);
1251     break;
1252     default:
1253     debug("unimplemented regimm5 = 0x%02x", regimm5);
1254     }
1255     break;
1256     default:
1257     debug("unimplemented hi6 = 0x%02x", hi6);
1258     }
1259    
1260     disasm_ret:
1261     debug("\n");
1262     return sizeof(instrword);
1263     }
1264    
1265    
1266     /*
1267     * mips_cpu_register_dump():
1268     *
1269     * Dump cpu registers in a relatively readable format.
1270     *
1271     * gprs: set to non-zero to dump GPRs and hi/lo/pc
1272     * coprocs: set bit 0..3 to dump registers in coproc 0..3.
1273     */
1274     void mips_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
1275     {
1276     int coprocnr, i, bits32;
1277     uint64_t offset;
1278     char *symbol;
1279    
1280     bits32 = (cpu->cd.mips.cpu_type.isa_level < 3 ||
1281     cpu->cd.mips.cpu_type.isa_level == 32)? 1 : 0;
1282    
1283     if (gprs) {
1284     /* Special registers (pc, hi/lo) first: */
1285     symbol = get_symbol_name(&cpu->machine->symbol_context,
1286     cpu->pc, &offset);
1287    
1288     if (bits32)
1289     debug("cpu%i: pc = %08x", cpu->cpu_id, (int)cpu->pc);
1290     else
1291     debug("cpu%i: pc = %016llx",
1292     cpu->cpu_id, (long long)cpu->pc);
1293    
1294     debug(" <%s>\n", symbol != NULL? symbol :
1295     " no symbol ");
1296    
1297     if (bits32)
1298     debug("cpu%i: hi = %08x lo = %08x\n",
1299     cpu->cpu_id, (int)cpu->cd.mips.hi, (int)cpu->cd.mips.lo);
1300     else
1301     debug("cpu%i: hi = %016llx lo = %016llx\n",
1302     cpu->cpu_id, (long long)cpu->cd.mips.hi,
1303     (long long)cpu->cd.mips.lo);
1304    
1305     /* General registers: */
1306     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
1307     /* 128-bit: */
1308     for (i=0; i<32; i++) {
1309     if ((i & 1) == 0)
1310     debug("cpu%i:", cpu->cpu_id);
1311     debug(" %3s=%016llx%016llx",
1312     regname(cpu->machine, i),
1313     (long long)cpu->cd.mips.gpr_quadhi[i],
1314     (long long)cpu->cd.mips.gpr[i]);
1315     if ((i & 1) == 1)
1316     debug("\n");
1317     }
1318     } else if (bits32) {
1319     /* 32-bit: */
1320     for (i=0; i<32; i++) {
1321     if ((i & 3) == 0)
1322     debug("cpu%i:", cpu->cpu_id);
1323     debug(" %3s = %08x", regname(cpu->machine, i),
1324     (int)cpu->cd.mips.gpr[i]);
1325     if ((i & 3) == 3)
1326     debug("\n");
1327     }
1328     } else {
1329     /* 64-bit: */
1330     for (i=0; i<32; i++) {
1331     if ((i & 1) == 0)
1332     debug("cpu%i:", cpu->cpu_id);
1333     debug(" %3s = %016llx",
1334     regname(cpu->machine, i),
1335     (long long)cpu->cd.mips.gpr[i]);
1336     if ((i & 1) == 1)
1337     debug("\n");
1338     }
1339     }
1340     }
1341    
1342     for (coprocnr=0; coprocnr<4; coprocnr++) {
1343     int nm1 = 1;
1344    
1345     if (bits32)
1346     nm1 = 3;
1347    
1348     if (!(coprocs & (1<<coprocnr)))
1349     continue;
1350     if (cpu->cd.mips.coproc[coprocnr] == NULL) {
1351     debug("cpu%i: no coprocessor %i\n",
1352     cpu->cpu_id, coprocnr);
1353     continue;
1354     }
1355    
1356     /* Coprocessor registers: */
1357     /* TODO: multiple selections per register? */
1358     for (i=0; i<32; i++) {
1359     /* 32-bit: */
1360     if ((i & nm1) == 0)
1361     debug("cpu%i:", cpu->cpu_id);
1362    
1363     if (cpu->machine->show_symbolic_register_names &&
1364     coprocnr == 0)
1365     debug(" %8s", cop0_names[i]);
1366     else
1367     debug(" c%i,%02i", coprocnr, i);
1368    
1369     if (bits32)
1370     debug("=%08x", (int)cpu->cd.mips.coproc[coprocnr]->reg[i]);
1371     else
1372     debug(" = 0x%016llx", (long long)
1373     cpu->cd.mips.coproc[coprocnr]->reg[i]);
1374    
1375     if ((i & nm1) == nm1)
1376     debug("\n");
1377    
1378     /* Skip the last 16 cop0 registers on R3000 etc. */
1379     if (coprocnr == 0 && cpu->cd.mips.cpu_type.isa_level < 3
1380     && i == 15)
1381     i = 31;
1382     }
1383    
1384     /* Floating point control registers: */
1385     if (coprocnr == 1) {
1386     for (i=0; i<32; i++)
1387     switch (i) {
1388     case 0: printf("cpu%i: fcr0 (fcir) = 0x%08x\n",
1389     cpu->cpu_id, (int)cpu->cd.mips.coproc[coprocnr]->fcr[i]);
1390     break;
1391     case 25:printf("cpu%i: fcr25 (fccr) = 0x%08x\n",
1392     cpu->cpu_id, (int)cpu->cd.mips.coproc[coprocnr]->fcr[i]);
1393     break;
1394     case 31:printf("cpu%i: fcr31 (fcsr) = 0x%08x\n",
1395     cpu->cpu_id, (int)cpu->cd.mips.coproc[coprocnr]->fcr[i]);
1396     break;
1397     }
1398     }
1399     }
1400     }
1401    
1402    
1403     /*
1404     * show_trace():
1405     *
1406     * Show trace tree. This function should be called every time
1407     * a function is called. cpu->cd.mips.trace_tree_depth is increased here
1408     * and should not be increased by the caller.
1409     *
1410     * Note: This function should not be called if show_trace_tree == 0.
1411     */
1412     static void show_trace(struct cpu *cpu, uint64_t addr)
1413     {
1414     uint64_t offset;
1415     int x, n_args_to_print;
1416     char strbuf[50];
1417     char *symbol;
1418    
1419     cpu->cd.mips.trace_tree_depth ++;
1420    
1421     if (cpu->machine->ncpus > 1)
1422     debug("cpu%i:", cpu->cpu_id);
1423    
1424     symbol = get_symbol_name(&cpu->machine->symbol_context, addr, &offset);
1425    
1426     for (x=0; x<cpu->cd.mips.trace_tree_depth; x++)
1427     debug(" ");
1428    
1429     /* debug("<%s>\n", symbol!=NULL? symbol : "no symbol"); */
1430    
1431     if (symbol != NULL)
1432     debug("<%s(", symbol);
1433     else {
1434     debug("<0x");
1435     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
1436     cpu->cd.mips.cpu_type.isa_level == 32)
1437     debug("%08x", (int)addr);
1438     else
1439     debug("%016llx", (long long)addr);
1440     debug("(");
1441     }
1442    
1443     /*
1444     * TODO: The number of arguments and the symbol type of each
1445     * argument should be taken from the symbol table, in some way.
1446     *
1447     * The MIPS binary calling convention is that the first 4
1448     * arguments are in registers a0..a3.
1449     *
1450     * Choose a value greater than 4 (eg 5) to print all values in
1451     * the A0..A3 registers and then add a ".." to indicate that
1452     * there might be more arguments.
1453     */
1454     n_args_to_print = 5;
1455    
1456     for (x=0; x<n_args_to_print; x++) {
1457     int64_t d = cpu->cd.mips.gpr[x + MIPS_GPR_A0];
1458    
1459     if (d > -256 && d < 256)
1460     debug("%i", (int)d);
1461     else if (memory_points_to_string(cpu, cpu->mem, d, 1))
1462     debug("\"%s\"", memory_conv_to_string(cpu,
1463     cpu->mem, d, strbuf, sizeof(strbuf)));
1464     else {
1465     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
1466     cpu->cd.mips.cpu_type.isa_level == 32)
1467     debug("0x%x", (int)d);
1468     else
1469     debug("0x%llx", (long long)d);
1470     }
1471    
1472     if (x < n_args_to_print - 1)
1473     debug(",");
1474    
1475     /* Cannot go beyound MIPS_GPR_A3: */
1476     if (x == 3)
1477     break;
1478     }
1479    
1480     if (n_args_to_print > 4)
1481     debug("..");
1482    
1483     debug(")>\n");
1484     }
1485    
1486    
1487     /*
1488     * mips_cpu_interrupt():
1489     *
1490     * Cause an interrupt. If irq_nr is 2..7, then it is a MIPS hardware
1491     * interrupt. 0 and 1 are ignored (software interrupts).
1492     *
1493     * If irq_nr is >= 8, then this function calls md_interrupt().
1494     */
1495     int mips_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
1496     {
1497     if (irq_nr >= 8) {
1498     if (cpu->machine->md_interrupt != NULL)
1499     cpu->machine->md_interrupt(cpu->machine, cpu, irq_nr, 1);
1500     else
1501     fatal("mips_cpu_interrupt(): irq_nr = %i, but md_interrupt = NULL ?\n", irq_nr);
1502     return 1;
1503     }
1504    
1505     if (irq_nr < 2)
1506     return 0;
1507    
1508     cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] |= ((1 << irq_nr) << STATUS_IM_SHIFT);
1509     cpu->cd.mips.cached_interrupt_is_possible = 1;
1510     return 1;
1511     }
1512    
1513    
1514     /*
1515     * mips_cpu_interrupt_ack():
1516     *
1517     * Acknowledge an interrupt. If irq_nr is 2..7, then it is a MIPS hardware
1518     * interrupt. Interrupts 0..1 are ignored (software interrupts).
1519     *
1520     * If irq_nr is >= 8, then it is machine dependant, and md_interrupt() is
1521     * called.
1522     */
1523     int mips_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
1524     {
1525     if (irq_nr >= 8) {
1526     if (cpu->machine->md_interrupt != NULL)
1527     cpu->machine->md_interrupt(cpu->machine, cpu, irq_nr, 0);
1528     else
1529     fatal("mips_cpu_interrupt_ack(): irq_nr = %i, but md_interrupt = NULL ?\n", irq_nr);
1530     return 1;
1531     }
1532    
1533     if (irq_nr < 2)
1534     return 0;
1535    
1536     cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] &= ~((1 << irq_nr) << STATUS_IM_SHIFT);
1537     if (!(cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] & STATUS_IM_MASK))
1538     cpu->cd.mips.cached_interrupt_is_possible = 0;
1539    
1540     return 1;
1541     }
1542    
1543    
1544     /*
1545     * mips_cpu_exception():
1546     *
1547     * Cause an exception in a CPU. This sets a couple of coprocessor 0
1548     * registers, and the program counter.
1549     *
1550     * exccode the exception code
1551     * tlb set to non-zero if the exception handler at
1552     * 0x80000000 should be used. (normal = 0x80000180)
1553     * vaddr virtual address (for some exceptions)
1554     * coproc_nr coprocessor number (for some exceptions)
1555     * vaddr_vpn2 vpn2 (for some exceptions)
1556     * vaddr_asid asid (for some exceptions)
1557     * x_64 non-zero for 64-bit mode for R4000-style tlb misses
1558     */
1559     void mips_cpu_exception(struct cpu *cpu, int exccode, int tlb, uint64_t vaddr,
1560     int coproc_nr, uint64_t vaddr_vpn2, int vaddr_asid, int x_64)
1561     {
1562     uint64_t base;
1563     uint64_t *reg = &cpu->cd.mips.coproc[0]->reg[0];
1564     int exc_model = cpu->cd.mips.cpu_type.exc_model;
1565    
1566     if (!quiet_mode) {
1567     uint64_t offset;
1568     int x;
1569     char *symbol = get_symbol_name(
1570     &cpu->machine->symbol_context, cpu->cd.mips.pc_last, &offset);
1571    
1572     debug("[ ");
1573     if (cpu->machine->ncpus > 1)
1574     debug("cpu%i: ", cpu->cpu_id);
1575    
1576     debug("exception %s%s",
1577     exception_names[exccode], tlb? " <tlb>" : "");
1578    
1579     switch (exccode) {
1580     case EXCEPTION_INT:
1581     debug(" cause_im=0x%02x", (int)((reg[COP0_CAUSE] & CAUSE_IP_MASK) >> CAUSE_IP_SHIFT));
1582     break;
1583     case EXCEPTION_SYS:
1584     debug(" v0=%i", (int)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1585     for (x=0; x<4; x++) {
1586     int64_t d = cpu->cd.mips.gpr[MIPS_GPR_A0 + x];
1587     char strbuf[30];
1588    
1589     if (d > -256 && d < 256)
1590     debug(" a%i=%i", x, (int)d);
1591     else if (memory_points_to_string(cpu, cpu->mem, d, 1))
1592     debug(" a%i=\"%s\"", x, memory_conv_to_string(cpu, cpu->mem, d, strbuf, sizeof(strbuf)));
1593     else
1594     debug(" a%i=0x%llx", x, (long long)d);
1595     }
1596     break;
1597     default:
1598     debug(" vaddr=0x%016llx", (long long)vaddr);
1599     }
1600    
1601     debug(" pc=%08llx ", (long long)cpu->cd.mips.pc_last);
1602    
1603     if (symbol != NULL)
1604     debug("<%s> ]\n", symbol);
1605     else
1606     debug("]\n");
1607     }
1608    
1609     if (tlb && vaddr < 0x1000) {
1610     uint64_t offset;
1611     char *symbol = get_symbol_name(
1612     &cpu->machine->symbol_context, cpu->cd.mips.pc_last, &offset);
1613     fatal("warning: LOW reference vaddr=0x%08x, exception %s, pc=%08llx <%s>\n",
1614     (int)vaddr, exception_names[exccode], (long long)cpu->cd.mips.pc_last, symbol? symbol : "(no symbol)");
1615     }
1616    
1617     /* Clear the exception code bits of the cause register... */
1618     if (exc_model == EXC3K) {
1619     reg[COP0_CAUSE] &= ~R2K3K_CAUSE_EXCCODE_MASK;
1620     #if 0
1621     if (exccode >= 16) {
1622     fatal("exccode = %i (there are only 16 exceptions on R3000 and lower)\n", exccode);
1623     cpu->running = 0;
1624     return;
1625     }
1626     #endif
1627     } else
1628     reg[COP0_CAUSE] &= ~CAUSE_EXCCODE_MASK;
1629    
1630     /* ... and OR in the exception code: */
1631     reg[COP0_CAUSE] |= (exccode << CAUSE_EXCCODE_SHIFT);
1632    
1633     /* Always set CE (according to the R5000 manual): */
1634     reg[COP0_CAUSE] &= ~CAUSE_CE_MASK;
1635     reg[COP0_CAUSE] |= (coproc_nr << CAUSE_CE_SHIFT);
1636    
1637     /* TODO: On R4000, vaddr should NOT be set on bus errors!!! */
1638     #if 0
1639     if (exccode == EXCEPTION_DBE) {
1640     reg[COP0_BADVADDR] = vaddr;
1641     /* sign-extend vaddr, if it is 32-bit */
1642     if ((vaddr >> 32) == 0 && (vaddr & 0x80000000ULL))
1643     reg[COP0_BADVADDR] |=
1644     0xffffffff00000000ULL;
1645     }
1646     #endif
1647    
1648     if (tlb || (exccode >= EXCEPTION_MOD && exccode <= EXCEPTION_ADES) ||
1649     exccode == EXCEPTION_VCEI || exccode == EXCEPTION_VCED) {
1650     reg[COP0_BADVADDR] = vaddr;
1651     #if 1
1652     /* TODO: This should be removed. */
1653     /* sign-extend vaddr, if it is 32-bit */
1654     if ((vaddr >> 32) == 0 && (vaddr & 0x80000000ULL))
1655     reg[COP0_BADVADDR] |=
1656     0xffffffff00000000ULL;
1657     #endif
1658     if (exc_model == EXC3K) {
1659     reg[COP0_CONTEXT] &= ~R2K3K_CONTEXT_BADVPN_MASK;
1660     reg[COP0_CONTEXT] |= ((vaddr_vpn2 << R2K3K_CONTEXT_BADVPN_SHIFT) & R2K3K_CONTEXT_BADVPN_MASK);
1661    
1662     reg[COP0_ENTRYHI] = (vaddr & R2K3K_ENTRYHI_VPN_MASK)
1663     | (vaddr_asid << R2K3K_ENTRYHI_ASID_SHIFT);
1664    
1665     /* Sign-extend: */
1666     reg[COP0_CONTEXT] = (int64_t)(int32_t)reg[COP0_CONTEXT];
1667     reg[COP0_ENTRYHI] = (int64_t)(int32_t)reg[COP0_ENTRYHI];
1668     } else {
1669     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1670     reg[COP0_CONTEXT] &= ~CONTEXT_BADVPN2_MASK_R4100;
1671     reg[COP0_CONTEXT] |= ((vaddr_vpn2 << CONTEXT_BADVPN2_SHIFT) & CONTEXT_BADVPN2_MASK_R4100);
1672    
1673     /* TODO: fix these */
1674     reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
1675     reg[COP0_XCONTEXT] &= ~XCONTEXT_BADVPN2_MASK;
1676     reg[COP0_XCONTEXT] |= (vaddr_vpn2 << XCONTEXT_BADVPN2_SHIFT) & XCONTEXT_BADVPN2_MASK;
1677     reg[COP0_XCONTEXT] |= ((vaddr >> 62) & 0x3) << XCONTEXT_R_SHIFT;
1678    
1679     /* reg[COP0_PAGEMASK] = cpu->cd.mips.coproc[0]->tlbs[0].mask & PAGEMASK_MASK; */
1680    
1681     reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK | 0x1800)) | vaddr_asid;
1682     } else {
1683     reg[COP0_CONTEXT] &= ~CONTEXT_BADVPN2_MASK;
1684     reg[COP0_CONTEXT] |= ((vaddr_vpn2 << CONTEXT_BADVPN2_SHIFT) & CONTEXT_BADVPN2_MASK);
1685    
1686     reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
1687     reg[COP0_XCONTEXT] &= ~XCONTEXT_BADVPN2_MASK;
1688     reg[COP0_XCONTEXT] |= (vaddr_vpn2 << XCONTEXT_BADVPN2_SHIFT) & XCONTEXT_BADVPN2_MASK;
1689     reg[COP0_XCONTEXT] |= ((vaddr >> 62) & 0x3) << XCONTEXT_R_SHIFT;
1690    
1691     /* reg[COP0_PAGEMASK] = cpu->cd.mips.coproc[0]->tlbs[0].mask & PAGEMASK_MASK; */
1692    
1693     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
1694     reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K)) | vaddr_asid;
1695     else
1696     reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK)) | vaddr_asid;
1697     }
1698     }
1699     }
1700    
1701     if (exc_model == EXC4K && reg[COP0_STATUS] & STATUS_EXL) {
1702     /*
1703     * Don't set EPC if STATUS_EXL is set, for R4000 and up.
1704     * This actually happens when running IRIX and Ultrix, when
1705     * they handle interrupts and/or tlb updates, I think, so
1706     * printing this with debug() looks better than with fatal().
1707     */
1708     /* debug("[ warning: cpu%i exception while EXL is set, not setting EPC ]\n", cpu->cpu_id); */
1709     } else {
1710     if (cpu->cd.mips.delay_slot || cpu->cd.mips.nullify_next) {
1711     reg[COP0_EPC] = cpu->cd.mips.pc_last - 4;
1712     reg[COP0_CAUSE] |= CAUSE_BD;
1713    
1714     /* TODO: Should the BD flag actually be set
1715     on nullified slots? */
1716     } else {
1717     reg[COP0_EPC] = cpu->cd.mips.pc_last;
1718     reg[COP0_CAUSE] &= ~CAUSE_BD;
1719     }
1720     }
1721    
1722     cpu->cd.mips.delay_slot = NOT_DELAYED;
1723     cpu->cd.mips.nullify_next = 0;
1724    
1725     /* TODO: This is true for MIPS64, but how about others? */
1726     if (reg[COP0_STATUS] & STATUS_BEV)
1727     base = 0xffffffffbfc00200ULL;
1728     else
1729     base = 0xffffffff80000000ULL;
1730    
1731     switch (exc_model) {
1732     case EXC3K:
1733     /* Userspace tlb, vs others: */
1734     if (tlb && !(vaddr & 0x80000000ULL) &&
1735     (exccode == EXCEPTION_TLBL || exccode == EXCEPTION_TLBS) )
1736     cpu->pc = base + 0x000;
1737     else
1738     cpu->pc = base + 0x080;
1739     break;
1740     default:
1741     /*
1742     * These offsets are according to the MIPS64 manual, but
1743     * should work with R4000 and the rest too (I hope).
1744     *
1745     * 0x000 TLB refill, if EXL=0
1746     * 0x080 64-bit XTLB refill, if EXL=0
1747     * 0x100 cache error (not implemented yet)
1748     * 0x180 general exception
1749     * 0x200 interrupt (if CAUSE_IV is set)
1750     */
1751     if (tlb && (exccode == EXCEPTION_TLBL ||
1752     exccode == EXCEPTION_TLBS) &&
1753     !(reg[COP0_STATUS] & STATUS_EXL)) {
1754     if (x_64)
1755     cpu->pc = base + 0x080;
1756     else
1757     cpu->pc = base + 0x000;
1758     } else {
1759     if (exccode == EXCEPTION_INT &&
1760     (reg[COP0_CAUSE] & CAUSE_IV))
1761     cpu->pc = base + 0x200;
1762     else
1763     cpu->pc = base + 0x180;
1764     }
1765     }
1766    
1767     if (exc_model == EXC3K) {
1768     /* R2000/R3000: Shift the lowest 6 bits to the left two steps: */
1769     reg[COP0_STATUS] =
1770     (reg[COP0_STATUS] & ~0x3f) +
1771     ((reg[COP0_STATUS] & 0xf) << 2);
1772     } else {
1773     /* R4000: */
1774     reg[COP0_STATUS] |= STATUS_EXL;
1775     }
1776    
1777     /* Sign-extend: */
1778     reg[COP0_CAUSE] = (int64_t)(int32_t)reg[COP0_CAUSE];
1779     reg[COP0_STATUS] = (int64_t)(int32_t)reg[COP0_STATUS];
1780     }
1781    
1782    
1783     #ifdef BINTRANS
1784     /*
1785     * mips_cpu_cause_simple_exception():
1786     *
1787     * Useful for causing raw exceptions from bintrans, for example
1788     * SYSCALL or BREAK.
1789     */
1790     void mips_cpu_cause_simple_exception(struct cpu *cpu, int exc_code)
1791     {
1792     mips_cpu_exception(cpu, exc_code, 0, 0, 0, 0, 0, 0);
1793     }
1794     #endif
1795    
1796    
1797     /* Included here for better cache characteristics: */
1798     #include "memory_mips.c"
1799    
1800    
1801     /*
1802     * mips_cpu_run_instr():
1803     *
1804     * Execute one instruction on a cpu.
1805     *
1806     * If we are in a delay slot, set cpu->pc to cpu->cd.mips.delay_jmpaddr
1807     * after the instruction is executed.
1808     *
1809     * Return value is the number of instructions executed during this call,
1810     * 0 if no instruction was executed.
1811     */
1812     int mips_cpu_run_instr(struct emul *emul, struct cpu *cpu)
1813     {
1814     int quiet_mode_cached = quiet_mode;
1815     int instruction_trace_cached = cpu->machine->instruction_trace;
1816     struct mips_coproc *cp0 = cpu->cd.mips.coproc[0];
1817     int i, tmp, ninstrs_executed;
1818     unsigned char instr[4];
1819     uint32_t instrword;
1820     uint64_t cached_pc;
1821     int hi6, special6, regimm5, rd, rs, rt, sa, imm;
1822     int copz, which_cache, cache_op;
1823    
1824     int cond, likely, and_link;
1825    
1826     /* for unaligned load/store */
1827     uint64_t dir, is_left, reg_ofs, reg_dir;
1828    
1829     uint64_t tmpvalue, tmpaddr;
1830    
1831     int cpnr; /* coprocessor nr */
1832    
1833     /* for load/store */
1834     uint64_t addr, value, value_hi, result_value;
1835     int wlen, st, signd, linked;
1836     unsigned char d[16]; /* room for at most 128 bits */
1837    
1838    
1839     /*
1840     * Update Coprocessor 0 registers:
1841     *
1842     * The COUNT register needs to be updated on every [other] instruction.
1843     * The RANDOM register should decrease for every instruction.
1844     */
1845    
1846     if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
1847     int r = (cp0->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK) >> R2K3K_RANDOM_SHIFT;
1848     r --;
1849     if (r >= cp0->nr_of_tlbs || r < 8)
1850     r = cp0->nr_of_tlbs-1;
1851     cp0->reg[COP0_RANDOM] = r << R2K3K_RANDOM_SHIFT;
1852     } else {
1853     cp0->reg[COP0_RANDOM] --;
1854     if ((int64_t)cp0->reg[COP0_RANDOM] >= cp0->nr_of_tlbs ||
1855     (int64_t)cp0->reg[COP0_RANDOM] < (int64_t) cp0->reg[COP0_WIRED])
1856     cp0->reg[COP0_RANDOM] = cp0->nr_of_tlbs-1;
1857    
1858     /*
1859     * TODO: only increase count every other instruction,
1860     * according to the R4000 manual. But according to the
1861     * R5000 manual: increment every other clock cycle.
1862     * Which one is it? :-)
1863     */
1864     cp0->reg[COP0_COUNT] = (int64_t)(int32_t)(cp0->reg[COP0_COUNT] + 1);
1865    
1866     if (cpu->cd.mips.compare_register_set &&
1867     cp0->reg[COP0_COUNT] == cp0->reg[COP0_COMPARE]) {
1868     mips_cpu_interrupt(cpu, 7);
1869     cpu->cd.mips.compare_register_set = 0;
1870     }
1871     }
1872    
1873    
1874     #ifdef ENABLE_INSTRUCTION_DELAYS
1875     if (cpu->cd.mips.instruction_delay > 0) {
1876     cpu->cd.mips.instruction_delay --;
1877     return 1;
1878     }
1879     #endif
1880    
1881     /* Cache the program counter in a local variable: */
1882     cached_pc = cpu->pc;
1883    
1884     /* Hardwire the zero register to 0: */
1885     cpu->cd.mips.gpr[MIPS_GPR_ZERO] = 0;
1886    
1887     if (cpu->cd.mips.delay_slot) {
1888     if (cpu->cd.mips.delay_slot == DELAYED) {
1889     cached_pc = cpu->pc = cpu->cd.mips.delay_jmpaddr;
1890     cpu->cd.mips.delay_slot = NOT_DELAYED;
1891     } else /* if (cpu->cd.mips.delay_slot == TO_BE_DELAYED) */ {
1892     /* next instruction will be delayed */
1893     cpu->cd.mips.delay_slot = DELAYED;
1894     }
1895     }
1896    
1897     if (cpu->cd.mips.last_was_jumptoself > 0)
1898     cpu->cd.mips.last_was_jumptoself --;
1899    
1900     /* Check PC against breakpoints: */
1901     if (!single_step)
1902     for (i=0; i<cpu->machine->n_breakpoints; i++)
1903     if (cached_pc == cpu->machine->breakpoint_addr[i]) {
1904     fatal("Breakpoint reached, pc=0x");
1905     if (cpu->cd.mips.cpu_type.isa_level < 3 ||
1906     cpu->cd.mips.cpu_type.isa_level == 32)
1907     fatal("%08x", (int)cached_pc);
1908     else
1909     fatal("%016llx", (long long)cached_pc);
1910     fatal("\n");
1911     single_step = 1;
1912     return 0;
1913     }
1914    
1915    
1916     /* Remember where we are, in case of interrupt or exception: */
1917     cpu->cd.mips.pc_last = cached_pc;
1918    
1919     /*
1920     * Any pending interrupts?
1921     *
1922     * If interrupts are enabled, and any interrupt has arrived (ie its
1923     * bit in the cause register is set) and corresponding enable bits
1924     * in the status register are set, then cause an interrupt exception
1925     * instead of executing the current instruction.
1926     *
1927     * NOTE: cached_interrupt_is_possible is set to 1 whenever an
1928     * interrupt bit in the cause register is set to one (in
1929     * mips_cpu_interrupt()) and set to 0 whenever all interrupt bits are
1930     * cleared (in mips_cpu_interrupt_ack()), so we don't need to do a
1931     * full check each time.
1932     */
1933     if (cpu->cd.mips.cached_interrupt_is_possible && !cpu->cd.mips.nullify_next) {
1934     if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
1935     /* R3000: */
1936     int enabled, mask;
1937     int status = cp0->reg[COP0_STATUS];
1938    
1939     enabled = status & MIPS_SR_INT_IE;
1940     mask = status & cp0->reg[COP0_CAUSE] & STATUS_IM_MASK;
1941     if (enabled && mask) {
1942     mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0, 0);
1943     return 0;
1944     }
1945     } else {
1946     /* R4000 and others: */
1947     int enabled, mask;
1948     int status = cp0->reg[COP0_STATUS];
1949    
1950     enabled = (status & STATUS_IE)
1951     && !(status & STATUS_EXL)
1952     && !(status & STATUS_ERL);
1953    
1954     mask = status & cp0->reg[COP0_CAUSE] & STATUS_IM_MASK;
1955     if (enabled && mask) {
1956     mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0, 0);
1957     return 0;
1958     }
1959     }
1960     }
1961    
1962    
1963     /*
1964     * ROM emulation:
1965     *
1966     * This assumes that a jal was made to a ROM address,
1967     * and we should return via gpr ra.
1968     */
1969     if ((cached_pc & 0xfff00000) == 0xbfc00000 &&
1970     cpu->machine->prom_emulation) {
1971     int rom_jal, res = 1;
1972     switch (cpu->machine->machine_type) {
1973     case MACHINE_DEC:
1974     res = decstation_prom_emul(cpu);
1975     rom_jal = 1;
1976     break;
1977     case MACHINE_PS2:
1978     res = playstation2_sifbios_emul(cpu);
1979     rom_jal = 1;
1980     break;
1981     case MACHINE_ARC:
1982     case MACHINE_SGI:
1983     res = arcbios_emul(cpu);
1984     rom_jal = 1;
1985     break;
1986     default:
1987     rom_jal = 0;
1988     }
1989    
1990     if (rom_jal) {
1991     /*
1992     * Special hack: If the PROM emulation layer needs
1993     * to loop (for example when emulating blocking
1994     * console input) then we should simply return, so
1995     * that the same PROM routine is called on the next
1996     * round as well.
1997     *
1998     * This still has to count as one or more
1999     * instructions, so 1000 is returned. (Ugly.)
2000     */
2001     if (!res)
2002     return 1000;
2003    
2004     cpu->pc = cpu->cd.mips.gpr[MIPS_GPR_RA];
2005     /* no need to update cached_pc, as we're returning */
2006     cpu->cd.mips.delay_slot = NOT_DELAYED;
2007    
2008     if (!quiet_mode_cached &&
2009     cpu->machine->show_trace_tree)
2010     cpu->cd.mips.trace_tree_depth --;
2011    
2012     /* TODO: how many instrs should this count as? */
2013     return 10;
2014     }
2015     }
2016    
2017     #ifdef ALWAYS_SIGNEXTEND_32
2018     /*
2019     * An extra check for 32-bit mode to make sure that all
2020     * registers are sign-extended: (Slow, but might be useful
2021     * to detect bugs that have to do with sign-extension.)
2022     */
2023     if (cpu->cd.mips.cpu_type.isa_level < 3 || cpu->cd.mips.cpu_type.isa_level == 32) {
2024     int warning = 0;
2025     uint64_t x;
2026    
2027     if (cpu->cd.mips.gpr[0] != 0) {
2028     fatal("\nWARNING: r0 was not zero! (%016llx)\n\n",
2029     (long long)cpu->cd.mips.gpr[0]);
2030     cpu->cd.mips.gpr[0] = 0;
2031     warning = 1;
2032     }
2033    
2034     if (cpu->pc != (int64_t)(int32_t)cpu->pc) {
2035     fatal("\nWARNING: pc was not sign-extended correctly"
2036     " (%016llx)\n\n", (long long)cpu->pc);
2037     cpu->pc = (int64_t)(int32_t)cpu->pc;
2038     warning = 1;
2039     }
2040    
2041     if (cpu->cd.mips.pc_last != (int64_t)(int32_t)cpu->cd.mips.pc_last) {
2042     fatal("\nWARNING: pc_last was not sign-extended correc"
2043     "tly (%016llx)\n\n", (long long)cpu->cd.mips.pc_last);
2044     cpu->cd.mips.pc_last = (int64_t)(int32_t)cpu->cd.mips.pc_last;
2045     warning = 1;
2046     }
2047    
2048     /* Sign-extend ALL registers, including coprocessor registers and tlbs: */
2049     for (i=1; i<32; i++) {
2050     x = cpu->cd.mips.gpr[i];
2051     cpu->cd.mips.gpr[i] &= 0xffffffff;
2052     if (cpu->cd.mips.gpr[i] & 0x80000000ULL)
2053     cpu->cd.mips.gpr[i] |= 0xffffffff00000000ULL;
2054     if (x != cpu->cd.mips.gpr[i]) {
2055     fatal("\nWARNING: r%i (%s) was not sign-"
2056     "extended correctly (%016llx != "
2057     "%016llx)\n\n", i, regname(cpu->machine, i),
2058     (long long)x, (long long)cpu->cd.mips.gpr[i]);
2059     warning = 1;
2060     }
2061     }
2062     for (i=0; i<32; i++) {
2063     x = cpu->cd.mips.coproc[0]->reg[i];
2064     cpu->cd.mips.coproc[0]->reg[i] &= 0xffffffffULL;
2065     if (cpu->cd.mips.coproc[0]->reg[i] & 0x80000000ULL)
2066     cpu->cd.mips.coproc[0]->reg[i] |=
2067     0xffffffff00000000ULL;
2068     if (x != cpu->cd.mips.coproc[0]->reg[i]) {
2069     fatal("\nWARNING: cop0,r%i was not sign-extended correctly (%016llx != %016llx)\n\n",
2070     i, (long long)x, (long long)cpu->cd.mips.coproc[0]->reg[i]);
2071     warning = 1;
2072     }
2073     }
2074     for (i=0; i<cpu->cd.mips.coproc[0]->nr_of_tlbs; i++) {
2075     x = cpu->cd.mips.coproc[0]->tlbs[i].hi;
2076     cpu->cd.mips.coproc[0]->tlbs[i].hi &= 0xffffffffULL;
2077     if (cpu->cd.mips.coproc[0]->tlbs[i].hi & 0x80000000ULL)
2078     cpu->cd.mips.coproc[0]->tlbs[i].hi |=
2079     0xffffffff00000000ULL;
2080     if (x != cpu->cd.mips.coproc[0]->tlbs[i].hi) {
2081     fatal("\nWARNING: tlb[%i].hi was not sign-extended correctly (%016llx != %016llx)\n\n",
2082     i, (long long)x, (long long)cpu->cd.mips.coproc[0]->tlbs[i].hi);
2083     warning = 1;
2084     }
2085    
2086     x = cpu->cd.mips.coproc[0]->tlbs[i].lo0;
2087     cpu->cd.mips.coproc[0]->tlbs[i].lo0 &= 0xffffffffULL;
2088     if (cpu->cd.mips.coproc[0]->tlbs[i].lo0 & 0x80000000ULL)
2089     cpu->cd.mips.coproc[0]->tlbs[i].lo0 |=
2090     0xffffffff00000000ULL;
2091     if (x != cpu->cd.mips.coproc[0]->tlbs[i].lo0) {
2092     fatal("\nWARNING: tlb[%i].lo0 was not sign-extended correctly (%016llx != %016llx)\n\n",
2093     i, (long long)x, (long long)cpu->cd.mips.coproc[0]->tlbs[i].lo0);
2094     warning = 1;
2095     }
2096     }
2097    
2098     if (warning) {
2099     fatal("Halting. pc = %016llx\n", (long long)cpu->pc);
2100     cpu->running = 0;
2101     }
2102     }
2103     #endif
2104    
2105     PREFETCH(cpu->cd.mips.pc_last_host_4k_page + (cached_pc & 0xfff));
2106    
2107     #ifdef HALT_IF_PC_ZERO
2108     /* Halt if PC = 0: */
2109     if (cached_pc == 0) {
2110     debug("cpu%i: pc=0, halting\n", cpu->cpu_id);
2111     cpu->running = 0;
2112     return 0;
2113     }
2114     #endif
2115    
2116    
2117    
2118     #ifdef BINTRANS
2119     /* Caches are not very coozy to handle in bintrans: */
2120     switch (cpu->cd.mips.cpu_type.mmu_model) {
2121     case MMU3K:
2122     if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & MIPS1_ISOL_CACHES) {
2123     /* cpu->cd.mips.dont_run_next_bintrans = 1; */
2124     cpu->cd.mips.vaddr_to_hostaddr_table0 =
2125     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & MIPS1_SWAP_CACHES?
2126     cpu->cd.mips.vaddr_to_hostaddr_table0_cacheisol_i
2127     : cpu->cd.mips.vaddr_to_hostaddr_table0_cacheisol_d;
2128     } else {
2129     cpu->cd.mips.vaddr_to_hostaddr_table0 =
2130     cpu->cd.mips.vaddr_to_hostaddr_table0_kernel;
2131    
2132     /* TODO: cpu->cd.mips.vaddr_to_hostaddr_table0_user; */
2133     }
2134     break;
2135     default:
2136     cpu->cd.mips.vaddr_to_hostaddr_table0 =
2137     cpu->cd.mips.vaddr_to_hostaddr_table0_kernel;
2138     /* TODO: cpu->cd.mips.vaddr_to_hostaddr_table0_user; */
2139     }
2140    
2141     if ((single_step || cpu->machine->instruction_trace)
2142     && cpu->machine->bintrans_enable)
2143     cpu->cd.mips.dont_run_next_bintrans = 1;
2144     #endif
2145    
2146    
2147     if (!quiet_mode_cached) {
2148     /* Dump CPU registers for debugging: */
2149     if (cpu->machine->register_dump) {
2150     debug("\n");
2151     mips_cpu_register_dump(cpu, 1, 0x1);
2152     }
2153    
2154     /* Trace tree: */
2155     if (cpu->machine->show_trace_tree && cpu->cd.mips.show_trace_delay > 0) {
2156     cpu->cd.mips.show_trace_delay --;
2157     if (cpu->cd.mips.show_trace_delay == 0)
2158     show_trace(cpu, cpu->cd.mips.show_trace_addr);
2159     }
2160     }
2161    
2162     #ifdef MFHILO_DELAY
2163     /* Decrease the MFHI/MFLO delays: */
2164     if (cpu->mfhi_delay > 0)
2165     cpu->mfhi_delay--;
2166     if (cpu->mflo_delay > 0)
2167     cpu->mflo_delay--;
2168     #endif
2169    
2170     /* Read an instruction from memory: */
2171     #ifdef ENABLE_MIPS16
2172     if (cpu->cd.mips.mips16 && (cached_pc & 1)) {
2173     /* 16-bit instruction word: */
2174     unsigned char instr16[2];
2175     int mips16_offset = 0;
2176    
2177     if (!cpu->memory_rw(cpu, cpu->mem, cached_pc ^ 1, &instr16[0],
2178     sizeof(instr16), MEM_READ, CACHE_INSTRUCTION))
2179     return 0;
2180    
2181     /* TODO: If Reverse-endian is set in the status cop0 register, and
2182     we are in usermode, then reverse endianness! */
2183    
2184     /* The rest of the code is written for little endian, so swap if necessary: */
2185     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2186     int tmp;
2187     tmp = instr16[0]; instr16[0] = instr16[1]; instr16[1] = tmp;
2188     }
2189    
2190     cpu->cd.mips.mips16_extend = 0;
2191    
2192     /*
2193     * Translate into 32-bit instruction, little endian (instr[3..0]):
2194     *
2195     * This ugly loop is necessary because if we would get an exception between
2196     * reading an extend instruction and the next instruction, and execution
2197     * continues on the second instruction, the extend data would be lost. So the
2198     * entire instruction (the two parts) need to be read in. If an exception is
2199     * caused, it will appear as if it was caused when reading the extend instruction.
2200     */
2201     while (mips16_to_32(cpu, instr16, instr) == 0) {
2202     if (instruction_trace_cached)
2203     debug("cpu%i @ %016llx: %02x%02x\t\t\textend\n",
2204     cpu->cpu_id, (cpu->cd.mips.pc_last ^ 1) + mips16_offset,
2205     instr16[1], instr16[0]);
2206    
2207     /* instruction with extend: */
2208     mips16_offset += 2;
2209     if (!cpu->memory_rw(cpu, cpu->mem, (cached_pc ^ 1) +
2210     mips16_offset, &instr16[0], sizeof(instr16),
2211     MEM_READ, CACHE_INSTRUCTION))
2212     return 0;
2213    
2214     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2215     int tmp;
2216     tmp = instr16[0]; instr16[0] = instr16[1]; instr16[1] = tmp;
2217     }
2218     }
2219    
2220     /* TODO: bintrans like in 32-bit mode? */
2221    
2222     /* Advance the program counter: */
2223     cpu->pc += sizeof(instr16) + mips16_offset;
2224     cached_pc = cpu->pc;
2225    
2226     if (instruction_trace_cached) {
2227     uint64_t offset;
2228     char *symbol = get_symbol_name(&cpu->machine->
2229     symbol_context, cpu->cd.mips.pc_last ^ 1, &offset);
2230     if (symbol != NULL && offset==0)
2231     debug("<%s>\n", symbol);
2232    
2233     debug("cpu%i @ %016llx: %02x%02x => %02x%02x%02x%02x%s\t",
2234     cpu->cpu_id, (cpu->cd.mips.pc_last ^ 1) + mips16_offset,
2235     instr16[1], instr16[0],
2236     instr[3], instr[2], instr[1], instr[0],
2237     cpu_flags(cpu));
2238     }
2239     } else
2240     #endif
2241     {
2242     /*
2243     * Fetch a 32-bit instruction word from memory:
2244     *
2245     * 1) The special case of reading an instruction from the
2246     * same host RAM page as the last one is handled here,
2247     * to gain a little bit performance.
2248     *
2249     * 2) Fallback to reading from memory the usual way.
2250     */
2251     if (cpu->cd.mips.pc_last_host_4k_page != NULL &&
2252     (cached_pc & ~0xfff) == cpu->cd.mips.pc_last_virtual_page) {
2253     /* NOTE: This only works on the host if offset is
2254     aligned correctly! (TODO) */
2255     *(uint32_t *)instr = *(uint32_t *)
2256     (cpu->cd.mips.pc_last_host_4k_page + (cached_pc & 0xfff));
2257     #ifdef BINTRANS
2258     cpu->cd.mips.pc_bintrans_paddr_valid = 1;
2259     cpu->cd.mips.pc_bintrans_paddr =
2260     cpu->cd.mips.pc_last_physical_page | (cached_pc & 0xfff);
2261     cpu->cd.mips.pc_bintrans_host_4kpage = cpu->cd.mips.pc_last_host_4k_page;
2262     #endif
2263     } else {
2264     if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
2265     sizeof(instr), MEM_READ, CACHE_INSTRUCTION))
2266     return 0;
2267     }
2268    
2269     #ifdef BINTRANS
2270     if (cpu->cd.mips.dont_run_next_bintrans) {
2271     cpu->cd.mips.dont_run_next_bintrans = 0;
2272     } else if (cpu->machine->bintrans_enable &&
2273     cpu->cd.mips.pc_bintrans_paddr_valid) {
2274     int res;
2275     cpu->cd.mips.bintrans_instructions_executed = 0;
2276    
2277     res = bintrans_attempt_translate(cpu,
2278     cpu->cd.mips.pc_bintrans_paddr);
2279    
2280     if (res >= 0) {
2281     /* debug("BINTRANS translation + hit,"
2282     " pc = %016llx\n", (long long)cached_pc); */
2283     if (res > 0 || cpu->pc != cached_pc) {
2284     if (instruction_trace_cached)
2285     mips_cpu_disassemble_instr(cpu, instr, 1, 0, 1);
2286     if (res & BINTRANS_DONT_RUN_NEXT)
2287     cpu->cd.mips.dont_run_next_bintrans = 1;
2288     res &= BINTRANS_N_MASK;
2289    
2290     if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
2291     /* TODO: 32-bit or 64-bit? */
2292     int x = cp0->reg[COP0_COUNT], y = cp0->reg[COP0_COMPARE];
2293     int diff = x - y;
2294     if (diff < 0 && diff + (res-1) >= 0
2295     && cpu->cd.mips.compare_register_set) {
2296     mips_cpu_interrupt(cpu, 7);
2297     cpu->cd.mips.compare_register_set = 0;
2298     }
2299    
2300     cp0->reg[COP0_COUNT] = (int64_t)
2301     (int32_t)(cp0->reg[COP0_COUNT] + res-1);
2302     }
2303    
2304     return res;
2305     }
2306     }
2307     }
2308     #endif
2309    
2310     if (instruction_trace_cached)
2311     mips_cpu_disassemble_instr(cpu, instr, 1, 0, 0);
2312    
2313     /* Advance the program counter: */
2314     cpu->pc += sizeof(instr);
2315     cached_pc = cpu->pc;
2316    
2317     /*
2318     * TODO: If Reverse-endian is set in the status cop0 register
2319     * and we are in usermode, then reverse endianness!
2320     */
2321    
2322     /*
2323     * The rest of the code is written for little endian, so
2324     * swap if necessary:
2325     */
2326     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2327     instrword = instr[0]; instr[0] = instr[3];
2328     instr[3] = instrword;
2329     instrword = instr[1]; instr[1] = instr[2];
2330     instr[2] = instrword;
2331     }
2332     }
2333    
2334    
2335     /*
2336     * Nullify this instruction? (Set by a previous branch-likely
2337     * instruction.)
2338     *
2339     * Note: The return value is 1, even if no instruction was actually
2340     * executed.
2341     */
2342     if (cpu->cd.mips.nullify_next) {
2343     cpu->cd.mips.nullify_next = 0;
2344     return 1;
2345     }
2346    
2347    
2348     /*
2349     * Execute the instruction:
2350     */
2351    
2352     /* Get the top 6 bits of the instruction: */
2353     hi6 = instr[3] >> 2; /* & 0x3f */
2354    
2355     if (show_opcode_statistics)
2356     cpu->cd.mips.stats_opcode[hi6] ++;
2357    
2358     switch (hi6) {
2359     case HI6_SPECIAL:
2360     special6 = instr[0] & 0x3f;
2361    
2362     if (show_opcode_statistics)
2363     cpu->cd.mips.stats__special[special6] ++;
2364    
2365     switch (special6) {
2366     case SPECIAL_SLL:
2367     case SPECIAL_SRL:
2368     case SPECIAL_SRA:
2369     case SPECIAL_DSLL:
2370     case SPECIAL_DSRL:
2371     case SPECIAL_DSRA:
2372     case SPECIAL_DSLL32:
2373     case SPECIAL_DSRL32:
2374     case SPECIAL_DSRA32:
2375     rt = instr[2] & 31;
2376     rd = (instr[1] >> 3) & 31;
2377     sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
2378    
2379     /*
2380     * Check for NOP:
2381     *
2382     * The R4000 manual says that a shift amount of zero
2383     * is treated as a nop by some assemblers. Checking
2384     * for sa == 0 here would not be correct, though,
2385     * because instructions such as sll r3,r4,0 are
2386     * possible, and are definitely not a nop.
2387     * Instead, check if the destination register is r0.
2388     *
2389     * TODO: ssnop should wait until the _next_
2390     * cycle boundary, or something like that. The
2391     * code here is incorrect.
2392     */
2393     if (rd == 0 && special6 == SPECIAL_SLL) {
2394     if (sa == 1) {
2395     /* ssnop */
2396     #ifdef ENABLE_INSTRUCTION_DELAYS
2397     cpu->cd.mips.instruction_delay +=
2398     cpu->cd.mips.cpu_type.
2399     instrs_per_cycle - 1;
2400     #endif
2401     }
2402     return 1;
2403     }
2404    
2405     if (special6 == SPECIAL_SLL) {
2406     switch (sa) {
2407     case 8: cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << 8; break;
2408     case 16:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << 16; break;
2409     default:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << sa;
2410     }
2411     /* Sign-extend rd: */
2412     cpu->cd.mips.gpr[rd] = (int64_t) (int32_t) cpu->cd.mips.gpr[rd];
2413     }
2414     if (special6 == SPECIAL_DSLL) {
2415     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << sa;
2416     }
2417     if (special6 == SPECIAL_DSRL) {
2418     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2419     }
2420     if (special6 == SPECIAL_DSLL32) {
2421     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << (sa + 32);
2422     }
2423     if (special6 == SPECIAL_SRL) {
2424     /*
2425     * Three cases:
2426     * shift amount = zero: just copy
2427     * high bit of rt zero: plain shift right (of all bits)
2428     * high bit of rt one: plain shift right (of lowest 32 bits)
2429     */
2430     if (sa == 0)
2431     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2432     else if (!(cpu->cd.mips.gpr[rt] & 0x80000000ULL)) {
2433     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2434     } else
2435     cpu->cd.mips.gpr[rd] = (cpu->cd.mips.gpr[rt] & 0xffffffffULL) >> sa;
2436     }
2437     if (special6 == SPECIAL_SRA) {
2438     int topbit = cpu->cd.mips.gpr[rt] & 0x80000000ULL;
2439     switch (sa) {
2440     case 8: cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> 8; break;
2441     case 16:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> 16; break;
2442     default:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2443     }
2444     if (topbit)
2445     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2446     }
2447     if (special6 == SPECIAL_DSRL32) {
2448     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> (sa + 32);
2449     }
2450     if (special6 == SPECIAL_DSRA32 || special6 == SPECIAL_DSRA) {
2451     if (special6 == SPECIAL_DSRA32)
2452     sa += 32;
2453     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2454     while (sa > 0) {
2455     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2456     sa--;
2457     if (cpu->cd.mips.gpr[rd] & ((uint64_t)1 << 62)) /* old signbit */
2458     cpu->cd.mips.gpr[rd] |= ((uint64_t)1 << 63);
2459     }
2460     }
2461     return 1;
2462     case SPECIAL_DSRLV:
2463     case SPECIAL_DSRAV:
2464     case SPECIAL_DSLLV:
2465     case SPECIAL_SLLV:
2466     case SPECIAL_SRAV:
2467     case SPECIAL_SRLV:
2468     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2469     rt = instr[2] & 31;
2470     rd = (instr[1] >> 3) & 31;
2471    
2472     if (special6 == SPECIAL_DSRLV) {
2473     sa = cpu->cd.mips.gpr[rs] & 63;
2474     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2475     }
2476     if (special6 == SPECIAL_DSRAV) {
2477     sa = cpu->cd.mips.gpr[rs] & 63;
2478     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2479     while (sa > 0) {
2480     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2481     sa--;
2482     if (cpu->cd.mips.gpr[rd] & ((uint64_t)1 << 62)) /* old sign-bit */
2483     cpu->cd.mips.gpr[rd] |= ((uint64_t)1 << 63);
2484     }
2485     }
2486     if (special6 == SPECIAL_DSLLV) {
2487     sa = cpu->cd.mips.gpr[rs] & 63;
2488     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2489     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] << sa;
2490     }
2491     if (special6 == SPECIAL_SLLV) {
2492     sa = cpu->cd.mips.gpr[rs] & 31;
2493     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2494     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] << sa;
2495     /* Sign-extend rd: */
2496     cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2497     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2498     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2499     }
2500     if (special6 == SPECIAL_SRAV) {
2501     sa = cpu->cd.mips.gpr[rs] & 31;
2502     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2503     /* Sign-extend rd: */
2504     cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2505     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2506     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2507     while (sa > 0) {
2508     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2509     sa--;
2510     }
2511     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2512     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2513     }
2514     if (special6 == SPECIAL_SRLV) {
2515     sa = cpu->cd.mips.gpr[rs] & 31;
2516     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2517     cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2518     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> sa;
2519     /* And finally sign-extend rd: */
2520     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2521     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2522     }
2523     return 1;
2524     case SPECIAL_JR:
2525     if (cpu->cd.mips.delay_slot) {
2526     fatal("jr: jump inside a jump's delay slot, or similar. TODO\n");
2527     cpu->running = 0;
2528     return 1;
2529     }
2530    
2531     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2532    
2533     cpu->cd.mips.delay_slot = TO_BE_DELAYED;
2534     cpu->cd.mips.delay_jmpaddr = cpu->cd.mips.gpr[rs];
2535    
2536     if (!quiet_mode_cached && cpu->machine->show_trace_tree
2537     && rs == 31) {
2538     cpu->cd.mips.trace_tree_depth --;
2539     }
2540    
2541     return 1;
2542     case SPECIAL_JALR:
2543     if (cpu->cd.mips.delay_slot) {
2544     fatal("jalr: jump inside a jump's delay slot, or similar. TODO\n");
2545     cpu->running = 0;
2546     return 1;
2547     }
2548    
2549     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2550     rd = (instr[1] >> 3) & 31;
2551    
2552     tmpvalue = cpu->cd.mips.gpr[rs];
2553     cpu->cd.mips.gpr[rd] = cached_pc + 4;
2554     /* already increased by 4 earlier */
2555    
2556     if (!quiet_mode_cached && cpu->machine->show_trace_tree
2557     && rd == 31) {
2558     cpu->cd.mips.show_trace_delay = 2;
2559     cpu->cd.mips.show_trace_addr = tmpvalue;
2560     }
2561    
2562     cpu->cd.mips.delay_slot = TO_BE_DELAYED;
2563     cpu->cd.mips.delay_jmpaddr = tmpvalue;
2564     return 1;
2565     case SPECIAL_MFHI:
2566     case SPECIAL_MFLO:
2567     rd = (instr[1] >> 3) & 31;
2568    
2569     if (special6 == SPECIAL_MFHI) {
2570     cpu->cd.mips.gpr[rd] = cpu->cd.mips.hi;
2571     #ifdef MFHILO_DELAY
2572     cpu->mfhi_delay = 3;
2573     #endif
2574     }
2575     if (special6 == SPECIAL_MFLO) {
2576     cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
2577     #ifdef MFHILO_DELAY
2578     cpu->mflo_delay = 3;
2579     #endif
2580     }
2581     return 1;
2582     case SPECIAL_ADD:
2583     case SPECIAL_ADDU:
2584     case SPECIAL_SUB:
2585     case SPECIAL_SUBU:
2586     case SPECIAL_AND:
2587     case SPECIAL_OR:
2588     case SPECIAL_XOR:
2589     case SPECIAL_NOR:
2590     case SPECIAL_SLT:
2591     case SPECIAL_SLTU:
2592     case SPECIAL_MTLO:
2593     case SPECIAL_MTHI:
2594     case SPECIAL_MULT:
2595     case SPECIAL_MULTU:
2596     case SPECIAL_DMULT:
2597     case SPECIAL_DMULTU:
2598     case SPECIAL_DIV:
2599     case SPECIAL_DIVU:
2600     case SPECIAL_DDIV:
2601     case SPECIAL_DDIVU:
2602     case SPECIAL_TGE:
2603     case SPECIAL_TGEU:
2604     case SPECIAL_TLT:
2605     case SPECIAL_TLTU:
2606     case SPECIAL_TEQ:
2607     case SPECIAL_TNE:
2608     case SPECIAL_DADD:
2609     case SPECIAL_DADDU:
2610     case SPECIAL_DSUB:
2611     case SPECIAL_DSUBU:
2612     case SPECIAL_MOVZ:
2613     case SPECIAL_MOVN:
2614     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2615     rt = instr[2] & 31;
2616     rd = (instr[1] >> 3) & 31;
2617    
2618     #ifdef MFHILO_DELAY
2619     if (cpu->mflo_delay > 0 && (
2620     special6 == SPECIAL_DDIV || special6 == SPECIAL_DDIVU ||
2621     special6 == SPECIAL_DIV || special6 == SPECIAL_DIVU ||
2622     special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU ||
2623     special6 == SPECIAL_MTLO || special6 == SPECIAL_MULT
2624     || special6 == SPECIAL_MULTU
2625     ) )
2626     debug("warning: instruction modifying LO too early after mflo!\n");
2627    
2628     if (cpu->mfhi_delay > 0 && (
2629     special6 == SPECIAL_DDIV || special6 == SPECIAL_DDIVU ||
2630     special6 == SPECIAL_DIV || special6 == SPECIAL_DIVU ||
2631     special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU ||
2632     special6 == SPECIAL_MTHI || special6 == SPECIAL_MULT
2633     || special6 == SPECIAL_MULTU
2634     ) )
2635     debug("warning: instruction modifying HI too early after mfhi!\n");
2636     #endif
2637    
2638     if (special6 == SPECIAL_ADDU) {
2639     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2640     cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2641     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2642     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2643     break;
2644     }
2645     if (special6 == SPECIAL_ADD) {
2646     /* According to the MIPS64 manual: */
2647     uint64_t temp, temp1, temp2;
2648     temp1 = cpu->cd.mips.gpr[rs] + ((cpu->cd.mips.gpr[rs] & 0x80000000ULL) << 1);
2649     temp2 = cpu->cd.mips.gpr[rt] + ((cpu->cd.mips.gpr[rt] & 0x80000000ULL) << 1);
2650     temp = temp1 + temp2;
2651     #if 0
2652     /* TODO: apparently this doesn't work (an example of
2653     something that breaks is NetBSD/sgimips' mips3_TBIA() */
2654     /* If bits 32 and 31 of temp differ, then it's an overflow */
2655     temp1 = temp & 0x100000000ULL;
2656     temp2 = temp & 0x80000000ULL;
2657     if ((temp1 && !temp2) || (!temp1 && temp2)) {
2658     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
2659     break;
2660     }
2661     #endif
2662     cpu->cd.mips.gpr[rd] = temp & 0xffffffffULL;
2663     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2664     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2665     break;
2666     }
2667     if (special6 == SPECIAL_SUBU) {
2668     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2669     cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2670     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2671     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2672     break;
2673     }
2674     if (special6 == SPECIAL_SUB) {
2675     /* According to the MIPS64 manual: */
2676     uint64_t temp, temp1, temp2;
2677     temp1 = cpu->cd.mips.gpr[rs] + ((cpu->cd.mips.gpr[rs] & 0x80000000ULL) << 1);
2678     temp2 = cpu->cd.mips.gpr[rt] + ((cpu->cd.mips.gpr[rt] & 0x80000000ULL) << 1);
2679     temp = temp1 - temp2;
2680     #if 0
2681     /* If bits 32 and 31 of temp differ, then it's an overflow */
2682     temp1 = temp & 0x100000000ULL;
2683     temp2 = temp & 0x80000000ULL;
2684     if ((temp1 && !temp2) || (!temp1 && temp2)) {
2685     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
2686     break;
2687     }
2688     #endif
2689     cpu->cd.mips.gpr[rd] = temp & 0xffffffffULL;
2690     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2691     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2692     break;
2693     }
2694    
2695     if (special6 == SPECIAL_AND) {
2696     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] & cpu->cd.mips.gpr[rt];
2697     break;
2698     }
2699     if (special6 == SPECIAL_OR) {
2700     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt];
2701     break;
2702     }
2703     if (special6 == SPECIAL_XOR) {
2704     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] ^ cpu->cd.mips.gpr[rt];
2705     break;
2706     }
2707     if (special6 == SPECIAL_NOR) {
2708     cpu->cd.mips.gpr[rd] = ~(cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt]);
2709     break;
2710     }
2711     if (special6 == SPECIAL_SLT) {
2712     cpu->cd.mips.gpr[rd] = (int64_t)cpu->cd.mips.gpr[rs] < (int64_t)cpu->cd.mips.gpr[rt];
2713     break;
2714     }
2715     if (special6 == SPECIAL_SLTU) {
2716     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] < cpu->cd.mips.gpr[rt];
2717     break;
2718     }
2719     if (special6 == SPECIAL_MTLO) {
2720     cpu->cd.mips.lo = cpu->cd.mips.gpr[rs];
2721     break;
2722     }
2723     if (special6 == SPECIAL_MTHI) {
2724     cpu->cd.mips.hi = cpu->cd.mips.gpr[rs];
2725     break;
2726     }
2727     if (special6 == SPECIAL_MULT) {
2728     int64_t f1, f2, sum;
2729     f1 = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2730     /* sign extend f1 */
2731     if (f1 & 0x80000000ULL)
2732     f1 |= 0xffffffff00000000ULL;
2733     f2 = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2734     /* sign extend f2 */
2735     if (f2 & 0x80000000ULL)
2736     f2 |= 0xffffffff00000000ULL;
2737     sum = f1 * f2;
2738    
2739     cpu->cd.mips.lo = sum & 0xffffffffULL;
2740     cpu->cd.mips.hi = ((uint64_t)sum >> 32) & 0xffffffffULL;
2741    
2742     /* sign-extend: */
2743     if (cpu->cd.mips.lo & 0x80000000ULL)
2744     cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2745     if (cpu->cd.mips.hi & 0x80000000ULL)
2746     cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2747    
2748     /*
2749     * NOTE: The stuff about rd!=0 is just a
2750     * guess, judging from how some NetBSD code
2751     * seems to execute. It is not documented in
2752     * the MIPS64 ISA docs :-/
2753     */
2754    
2755     if (rd != 0) {
2756     if (cpu->cd.mips.cpu_type.rev != MIPS_R5900)
2757     debug("WARNING! mult_xx is an undocumented instruction!");
2758     cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
2759     }
2760     break;
2761     }
2762     if (special6 == SPECIAL_MULTU) {
2763     uint64_t f1, f2, sum;
2764     /* zero extend f1 and f2 */
2765     f1 = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2766     f2 = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2767     sum = f1 * f2;
2768     cpu->cd.mips.lo = sum & 0xffffffffULL;
2769     cpu->cd.mips.hi = (sum >> 32) & 0xffffffffULL;
2770    
2771     /* sign-extend: */
2772     if (cpu->cd.mips.lo & 0x80000000ULL)
2773     cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2774     if (cpu->cd.mips.hi & 0x80000000ULL)
2775     cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2776     break;
2777     }
2778     /*
2779     * TODO: I'm too tired to think now. DMULT is probably
2780     * correct, but is DMULTU? (Unsigned 64x64 multiply.)
2781     * Or, hm, perhaps it is dmult which is incorrect.
2782     */
2783     if (special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU) {
2784     /* 64x64 = 128 bit multiplication: SLOW!!! TODO */
2785     uint64_t i, low_add, high_add;
2786    
2787     cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2788     for (i=0; i<64; i++) {
2789     uint64_t bit = cpu->cd.mips.gpr[rt] & ((uint64_t)1 << i);
2790     if (bit) {
2791     /* Add cpu->cd.mips.gpr[rs] to hi and lo: */
2792     low_add = (cpu->cd.mips.gpr[rs] << i);
2793     high_add = (cpu->cd.mips.gpr[rs] >> (64-i));
2794     if (i==0) /* WEIRD BUG in the compiler? Or maybe I'm just stupid */
2795     high_add = 0; /* these lines are necessary, a >> 64 doesn't seem to do anything */
2796     if (cpu->cd.mips.lo + low_add < cpu->cd.mips.lo)
2797     cpu->cd.mips.hi ++;
2798     cpu->cd.mips.lo += low_add;
2799     cpu->cd.mips.hi += high_add;
2800     }
2801     }
2802     break;
2803     }
2804     if (special6 == SPECIAL_DIV) {
2805     int64_t a, b;
2806     /* Signextend rs and rt: */
2807     a = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2808     if (a & 0x80000000ULL)
2809     a |= 0xffffffff00000000ULL;
2810     b = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2811     if (b & 0x80000000ULL)
2812     b |= 0xffffffff00000000ULL;
2813    
2814     if (b == 0) {
2815     /* undefined */
2816     cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2817     } else {
2818     cpu->cd.mips.lo = a / b;
2819     cpu->cd.mips.hi = a % b;
2820     }
2821     /* Sign-extend lo and hi: */
2822     cpu->cd.mips.lo &= 0xffffffffULL;
2823     if (cpu->cd.mips.lo & 0x80000000ULL)
2824     cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2825     cpu->cd.mips.hi &= 0xffffffffULL;
2826     if (cpu->cd.mips.hi & 0x80000000ULL)
2827     cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2828     break;
2829     }
2830     if (special6 == SPECIAL_DIVU) {
2831     int64_t a, b;
2832     /* Zero-extend rs and rt: */
2833     a = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2834     b = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2835     if (b == 0) {
2836     /* undefined */
2837     cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2838     } else {
2839     cpu->cd.mips.lo = a / b;
2840     cpu->cd.mips.hi = a % b;
2841     }
2842     /* Sign-extend lo and hi: */
2843     cpu->cd.mips.lo &= 0xffffffffULL;
2844     if (cpu->cd.mips.lo & 0x80000000ULL)
2845     cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2846     cpu->cd.mips.hi &= 0xffffffffULL;
2847     if (cpu->cd.mips.hi & 0x80000000ULL)
2848     cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2849     break;
2850     }
2851     if (special6 == SPECIAL_DDIV) {
2852     if (cpu->cd.mips.gpr[rt] == 0) {
2853     cpu->cd.mips.lo = cpu->cd.mips.hi = 0; /* undefined */
2854     } else {
2855     cpu->cd.mips.lo = (int64_t)cpu->cd.mips.gpr[rs] / (int64_t)cpu->cd.mips.gpr[rt];
2856     cpu->cd.mips.hi = (int64_t)cpu->cd.mips.gpr[rs] % (int64_t)cpu->cd.mips.gpr[rt];
2857     }
2858     break;
2859     }
2860     if (special6 == SPECIAL_DDIVU) {
2861     if (cpu->cd.mips.gpr[rt] == 0) {
2862     cpu->cd.mips.lo = cpu->cd.mips.hi = 0; /* undefined */
2863     } else {
2864     cpu->cd.mips.lo = cpu->cd.mips.gpr[rs] / cpu->cd.mips.gpr[rt];
2865     cpu->cd.mips.hi = cpu->cd.mips.gpr[rs] % cpu->cd.mips.gpr[rt];
2866     }
2867     break;
2868     }
2869     if (special6 == SPECIAL_TGE) {
2870     if ((int64_t)cpu->cd.mips.gpr[rs] >= (int64_t)cpu->cd.mips.gpr[rt])
2871     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2872     break;
2873     }
2874     if (special6 == SPECIAL_TGEU) {
2875     if (cpu->cd.mips.gpr[rs] >= cpu->cd.mips.gpr[rt])
2876     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2877     break;
2878     }
2879     if (special6 == SPECIAL_TLT) {
2880     if ((int64_t)cpu->cd.mips.gpr[rs] < (int64_t)cpu->cd.mips.gpr[rt])
2881     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2882     break;
2883     }
2884     if (special6 == SPECIAL_TLTU) {
2885     if (cpu->cd.mips.gpr[rs] < cpu->cd.mips.gpr[rt])
2886     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2887     break;
2888     }
2889     if (special6 == SPECIAL_TEQ) {
2890     if (cpu->cd.mips.gpr[rs] == cpu->cd.mips.gpr[rt])
2891     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2892     break;
2893     }
2894     if (special6 == SPECIAL_TNE) {
2895     if (cpu->cd.mips.gpr[rs] != cpu->cd.mips.gpr[rt])
2896     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2897     break;
2898     }
2899     if (special6 == SPECIAL_DADD) {
2900     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2901     /* TODO: exception on overflow */
2902     break;
2903     }
2904     if (special6 == SPECIAL_DADDU) {
2905     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2906     break;
2907     }
2908     if (special6 == SPECIAL_DSUB) {
2909     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2910     /* TODO: exception on overflow */
2911     break;
2912     }
2913     if (special6 == SPECIAL_DSUBU) {
2914     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2915     break;
2916     }
2917     if (special6 == SPECIAL_MOVZ) {
2918     if (cpu->cd.mips.gpr[rt] == 0)
2919     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs];
2920     break;
2921     }
2922     if (special6 == SPECIAL_MOVN) {
2923     if (cpu->cd.mips.gpr[rt] != 0)
2924     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs];
2925     return 1;
2926     }
2927     return 1;
2928     case SPECIAL_SYNC:
2929     imm = ((instr[1] & 7) << 2) + (instr[0] >> 6);
2930     /* TODO: actually sync */
2931    
2932     /* Clear the LLbit (at least on R10000): */
2933     cpu->cd.mips.rmw = 0;
2934     return 1;
2935     case SPECIAL_SYSCALL:
2936     imm = ((instr[3] << 24) + (instr[2] << 16) +
2937     (instr[1] << 8) + instr[0]) >> 6;
2938     imm &= 0xfffff;
2939    
2940     if (cpu->machine->userland_emul != NULL)
2941     useremul_syscall(cpu, imm);
2942     else
2943     mips_cpu_exception(cpu, EXCEPTION_SYS,
2944     0, 0, 0, 0, 0, 0);
2945     return 1;
2946     case SPECIAL_BREAK:
2947     mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
2948     return 1;
2949     case SPECIAL_MFSA:
2950     /* R5900? What on earth does this thing do? */
2951     rd = (instr[1] >> 3) & 31;
2952     /* TODO */
2953     return 1;
2954     case SPECIAL_MTSA:
2955     /* R5900? What on earth does this thing do? */
2956     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2957     /* TODO */
2958     return 1;
2959     default:
2960     if (!instruction_trace_cached) {
2961     fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
2962     cpu->cpu_id, cpu->cd.mips.pc_last,
2963     instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
2964     }
2965     fatal("unimplemented special6 = 0x%02x\n", special6);
2966     cpu->running = 0;
2967     return 1;
2968     }
2969     return 1;
2970     case HI6_BEQ:
2971     case HI6_BEQL:
2972     case HI6_BNE:
2973     case HI6_BGTZ:
2974     case HI6_BGTZL:
2975     case HI6_BLEZ:
2976     case HI6_BLEZL:
2977     case HI6_BNEL:
2978     case HI6_ADDI:
2979     case HI6_ADDIU:
2980     case HI6_DADDI:
2981     case HI6_DADDIU:
2982     case HI6_SLTI:
2983     case HI6_SLTIU:
2984     case HI6_ANDI:
2985     case HI6_ORI:
2986     case HI6_XORI:
2987     case HI6_LUI:
2988     case HI6_LB:
2989     case HI6_LBU:
2990     case HI6_LH:
2991     case HI6_LHU:
2992     case HI6_LW:
2993     case HI6_LWU:
2994     case HI6_LD:
2995     case HI6_LQ_MDMX:
2996     case HI6_LWC1:
2997     case HI6_LWC2:
2998     case HI6_LWC3:
2999     case HI6_LDC1:
3000     case HI6_LDC2:
3001     case HI6_LL:
3002     case HI6_LLD:
3003     case HI6_SB:
3004     case HI6_SH:
3005     case HI6_SW:
3006     case HI6_SD:
3007     case HI6_SQ:
3008     case HI6_SC:
3009     case HI6_SCD:
3010     case HI6_SWC1:
3011     case HI6_SWC2:
3012     case HI6_SWC3:
3013     case HI6_SDC1:
3014     case HI6_SDC2:
3015     case HI6_LWL: /* Unaligned load/store */
3016     case HI6_LWR:
3017     case HI6_LDL:
3018     case HI6_LDR:
3019     case HI6_SWL:
3020     case HI6_SWR:
3021     case HI6_SDL:
3022     case HI6_SDR:
3023     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3024     rt = instr[2] & 31;
3025     imm = (instr[1] << 8) + instr[0];
3026     if (imm >= 32768) /* signed 16-bit */
3027     imm -= 65536;
3028    
3029     tmpvalue = imm; /* used later in several cases */
3030    
3031     switch (hi6) {
3032     case HI6_ADDI:
3033     case HI6_ADDIU:
3034     case HI6_DADDI:
3035     case HI6_DADDIU:
3036     tmpvalue = cpu->cd.mips.gpr[rs];
3037     result_value = cpu->cd.mips.gpr[rs] + imm;
3038    
3039     if (hi6 == HI6_ADDI || hi6 == HI6_DADDI) {
3040     /*
3041     * addi and daddi should trap on overflow:
3042     *
3043     * TODO: This is incorrect? The R4000 manual
3044     * says that overflow occurs if the carry bits
3045     * out of bit 62 and 63 differ. The
3046     * destination register should not be modified
3047     * on overflow.
3048     */
3049     if (imm >= 0) {
3050     /* Turn around from 0x7fff.. to 0x800 ? Then overflow. */
3051     if ( ((hi6 == HI6_ADDI && (result_value &
3052     0x80000000ULL) && (tmpvalue &
3053     0x80000000ULL)==0))
3054     || ((hi6 == HI6_DADDI && (result_value &
3055     0x8000000000000000ULL) && (tmpvalue &
3056     0x8000000000000000ULL)==0)) ) {
3057     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
3058     break;
3059     }
3060     } else {
3061     /* Turn around from 0x8000.. to 0x7fff.. ? Then overflow. */
3062     if ( ((hi6 == HI6_ADDI && (result_value &
3063     0x80000000ULL)==0 && (tmpvalue &
3064     0x80000000ULL)))
3065     || ((hi6 == HI6_DADDI && (result_value &
3066     0x8000000000000000ULL)==0 && (tmpvalue &
3067     0x8000000000000000ULL))) ) {
3068     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
3069     break;
3070     }
3071     }
3072     }
3073    
3074     cpu->cd.mips.gpr[rt] = result_value;
3075    
3076     /*
3077     * Super-ugly speed-hack: (only if speed_tricks != 0)
3078     * NOTE: This makes the emulation less correct.
3079     *
3080     * If we encounter a loop such as:
3081     *
3082     * 8012f5f4: 1c40ffff bgtz r0,r2,ffffffff8012f5f4
3083     * 8012f5f8: 2442ffff (d) addiu r2,r2,-1
3084     *
3085     * then it is a small loop which simply waits for r2
3086     * to become zero.
3087     *
3088     * TODO: increaste the count register, and cause
3089     * interrupts!!! For now: return as if we just
3090     * executed 1 instruction.
3091     */
3092     ninstrs_executed = 1;
3093     if (cpu->machine->speed_tricks && cpu->cd.mips.delay_slot &&
3094     cpu->cd.mips.last_was_jumptoself &&
3095     cpu->cd.mips.jump_to_self_reg == rt &&
3096     cpu->cd.mips.jump_to_self_reg == rs) {
3097     if ((int64_t)cpu->cd.mips.gpr[rt] > 1 && (int64_t)cpu->cd.mips.gpr[rt] < 0x70000000
3098     && (imm >= -30000 && imm <= -1)) {
3099     if (instruction_trace_cached)
3100     debug("changing r%i from %016llx to", rt, (long long)cpu->cd.mips.gpr[rt]);
3101    
3102     while ((int64_t)cpu->cd.mips.gpr[rt] > 0 && ninstrs_executed < 1000
3103     && ((int64_t)cpu->cd.mips.gpr[rt] + (int64_t)imm) > 0) {
3104     cpu->cd.mips.gpr[rt] += (int64_t)imm;
3105     ninstrs_executed += 2;
3106     }
3107    
3108     if (instruction_trace_cached)
3109     debug(" %016llx\n", (long long)cpu->cd.mips.gpr[rt]);
3110    
3111     /* TODO: return value, cpu->cd.mips.gpr[rt] * 2; */
3112     }
3113     if ((int64_t)cpu->cd.mips.gpr[rt] > -0x70000000 && (int64_t)cpu->cd.mips.gpr[rt] < -1
3114     && (imm >= 1 && imm <= 30000)) {
3115     if (instruction_trace_cached)
3116     debug("changing r%i from %016llx to", rt, (long long)cpu->cd.mips.gpr[rt]);
3117    
3118     while ((int64_t)cpu->cd.mips.gpr[rt] < 0 && ninstrs_executed < 1000
3119     && ((int64_t)cpu->cd.mips.gpr[rt] + (int64_t)imm) < 0) {
3120     cpu->cd.mips.gpr[rt] += (int64_t)imm;
3121     ninstrs_executed += 2;
3122     }
3123    
3124     if (instruction_trace_cached)
3125     debug(" %016llx\n", (long long)cpu->cd.mips.gpr[rt]);
3126     }
3127     }
3128    
3129     if (hi6 == HI6_ADDI || hi6 == HI6_ADDIU) {
3130     /* Sign-extend: */
3131     cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
3132     if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
3133     cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
3134     }
3135     return ninstrs_executed;
3136     case HI6_BEQ:
3137     case HI6_BNE:
3138     case HI6_BGTZ:
3139     case HI6_BGTZL:
3140     case HI6_BLEZ:
3141     case HI6_BLEZL:
3142     case HI6_BEQL:
3143     case HI6_BNEL:
3144     if (cpu->cd.mips.delay_slot) {
3145     fatal("b*: jump inside a jump's delay slot, or similar. TODO\n");
3146     cpu->running = 0;
3147     return 1;
3148     }
3149     likely = cond = 0;
3150     switch (hi6) {
3151     case HI6_BNEL: likely = 1;
3152     case HI6_BNE: cond = (cpu->cd.mips.gpr[rt] != cpu->cd.mips.gpr[rs]);
3153     break;
3154     case HI6_BEQL: likely = 1;
3155     case HI6_BEQ: cond = (cpu->cd.mips.gpr[rt] == cpu->cd.mips.gpr[rs]);
3156     break;
3157     case HI6_BLEZL: likely = 1;
3158     case HI6_BLEZ: cond = ((int64_t)cpu->cd.mips.gpr[rs] <= 0);
3159     break;
3160     case HI6_BGTZL: likely = 1;
3161     case HI6_BGTZ: cond = ((int64_t)cpu->cd.mips.gpr[rs] > 0);
3162     break;
3163     }
3164    
3165     if (cond) {
3166     cpu->cd.mips.delay_slot = TO_BE_DELAYED;
3167     cpu->cd.mips.delay_jmpaddr = cached_pc + (imm << 2);
3168     } else {
3169     if (likely)
3170     cpu->cd.mips.nullify_next = 1; /* nullify delay slot */
3171     }
3172    
3173     if (imm==-1 && (hi6 == HI6_BGTZ || hi6 == HI6_BLEZ ||
3174     (hi6 == HI6_BGTZL && cond) ||
3175     (hi6 == HI6_BLEZL && cond) ||
3176     (hi6 == HI6_BNE && (rt==0 || rs==0)) ||
3177     (hi6 == HI6_BEQ && (rt==0 || rs==0)))) {
3178     cpu->cd.mips.last_was_jumptoself = 2;
3179     if (rs == 0)
3180     cpu->cd.mips.jump_to_self_reg = rt;
3181     else
3182     cpu->cd.mips.jump_to_self_reg = rs;
3183     }
3184     return 1;
3185     case HI6_LUI:
3186     cpu->cd.mips.gpr[rt] = (imm << 16);
3187     /* No sign-extending necessary, as imm already
3188     was sign-extended if it was negative. */
3189     break;
3190     case HI6_SLTI:
3191     cpu->cd.mips.gpr[rt] = (int64_t)cpu->cd.mips.gpr[rs] < (int64_t)tmpvalue;
3192     break;
3193     case HI6_SLTIU:
3194     cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] < (uint64_t)imm;
3195     break;
3196     case HI6_ANDI:
3197     cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] & (tmpvalue & 0xffff);
3198     break;
3199     case HI6_ORI:
3200     cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] | (tmpvalue & 0xffff);
3201     break;
3202     case HI6_XORI:
3203     cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] ^ (tmpvalue & 0xffff);
3204     break;
3205     case HI6_LB:
3206     case HI6_LBU:
3207     case HI6_LH:
3208     case HI6_LHU:
3209     case HI6_LW:
3210     case HI6_LWU:
3211     case HI6_LD:
3212     case HI6_LQ_MDMX:
3213     case HI6_LWC1:
3214     case HI6_LWC2:
3215     case HI6_LWC3: /* pref */
3216     case HI6_LDC1:
3217     case HI6_LDC2:
3218     case HI6_LL:
3219     case HI6_LLD:
3220     case HI6_SB:
3221     case HI6_SH:
3222     case HI6_SW:
3223     case HI6_SD:
3224     case HI6_SQ:
3225     case HI6_SC:
3226     case HI6_SCD:
3227     case HI6_SWC1:
3228     case HI6_SWC2:
3229     case HI6_SWC3:
3230     case HI6_SDC1:
3231     case HI6_SDC2:
3232     /* These are the default "assumptions". */
3233     linked = 0;
3234     st = 1;
3235     signd = 1;
3236     wlen = 4;
3237    
3238     switch (hi6) {
3239     /* The most common ones: */
3240     case HI6_LW: { st = 0; } break;
3241     case HI6_SW: { signd = 0; } break;
3242    
3243     case HI6_LB: { wlen = 1; st = 0; } break;
3244     case HI6_LBU: { wlen = 1; st = 0; signd = 0; } break;
3245     case HI6_SB: { wlen = 1; signd = 0; } break;
3246    
3247     case HI6_LD: { wlen = 8; st = 0; signd = 0; } break;
3248     case HI6_SD: { wlen = 8; signd = 0; } break;
3249    
3250     case HI6_LQ_MDMX: { wlen = 16; st = 0; signd = 0; } break; /* R5900, otherwise MDMX (TODO) */
3251     case HI6_SQ: { wlen = 16; signd = 0; } break; /* R5900 ? */
3252    
3253     /* The rest: */
3254     case HI6_LH: { wlen = 2; st = 0; } break;
3255     case HI6_LHU: { wlen = 2; st = 0; signd = 0; } break;
3256     case HI6_LWU: { st = 0; signd = 0; } break;
3257     case HI6_LWC1: { st = 0; } break;
3258     case HI6_LWC2: { st = 0; } break;
3259     case HI6_LWC3: { st = 0; } break;
3260     case HI6_LDC1: { wlen = 8; st = 0; signd = 0; } break;
3261     case HI6_LDC2: { wlen = 8; st = 0; signd = 0; } break;
3262    
3263     case HI6_SH: { wlen = 2; signd = 0; } break;
3264     case HI6_SDC1:
3265     case HI6_SDC2: wlen = 8;
3266     case HI6_SWC1:
3267     case HI6_SWC2:
3268     case HI6_SWC3: { signd = 0; } break;
3269    
3270     case HI6_LL: { st = 0; signd = 1; linked = 1; } break;
3271     case HI6_LLD: { wlen = 8; st = 0; signd = 0; linked = 1; } break;
3272    
3273     case HI6_SC: { signd = 1; linked = 1; } break;
3274     case HI6_SCD: { wlen = 8; signd = 0; linked = 1; } break;
3275    
3276     default:
3277     fatal("cannot be here\n");
3278     wlen = 4; st = 0; signd = 0;
3279     }
3280    
3281     /*
3282     * In the MIPS IV ISA, the 'lwc3' instruction is changed into 'pref'.
3283     * The pref instruction is emulated by not doing anything. :-) TODO
3284     */
3285     if (hi6 == HI6_LWC3 && cpu->cd.mips.cpu_type.isa_level >= 4) {
3286     /* Clear the LLbit (at least on R10000): */
3287     cpu->cd.mips.rmw = 0;
3288     break;
3289     }
3290    
3291     addr = cpu->cd.mips.gpr[rs] + imm;
3292    
3293     /* Check for natural alignment: */
3294     if ((addr & (wlen - 1)) != 0) {
3295     mips_cpu_exception(cpu, st? EXCEPTION_ADES : EXCEPTION_ADEL,
3296     0, addr, 0, 0, 0, 0);
3297     break;
3298     }
3299    
3300     #if 0
3301     if (cpu->cd.mips.cpu_type.isa_level == 4 && (imm & (wlen - 1)) != 0)
3302     debug("WARNING: low bits of imm value not zero! (MIPS IV) "
3303     "pc=%016llx", (long long)cpu->cd.mips.pc_last);
3304     #endif
3305    
3306     /*
3307     * Load Linked: This initiates a Read-Modify-Write
3308     * sequence.
3309     */
3310     if (linked) {
3311     if (st==0) {
3312     /* st == 0: Load */
3313     cpu->cd.mips.rmw = 1;
3314     cpu->cd.mips.rmw_addr = addr;
3315     cpu->cd.mips.rmw_len = wlen;
3316    
3317     /*
3318     * COP0_LLADDR is updated for
3319     * diagnostic purposes, except for
3320     * CPUs in the R10000 family.
3321     */
3322     if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
3323     cp0->reg[COP0_LLADDR] =
3324     (addr >> 4) & 0xffffffffULL;
3325     } else {
3326     /*
3327     * st == 1: Store
3328     * If rmw is 0, then the store failed.
3329     * (This cache-line was written to by
3330     * someone else.)
3331     */
3332     if (cpu->cd.mips.rmw == 0) {
3333     /* The store failed: */
3334     cpu->cd.mips.gpr[rt] = 0;
3335     if (instruction_trace_cached)
3336     debug(" [COLLISION] ");
3337     break;
3338     }
3339     }
3340     } else {
3341     /*
3342     * If any kind of load or store occurs between
3343     * an ll and an sc, then the ll-sc sequence
3344     * should fail. (This is local to each cpu.)
3345     */
3346     cpu->cd.mips.rmw = 0;
3347     }
3348    
3349     value_hi = 0;
3350    
3351     if (st) {
3352     /* store: */
3353     int cpnr, success;
3354    
3355     if (hi6 == HI6_SWC3 || hi6 == HI6_SWC2 ||
3356     hi6 == HI6_SDC1 || hi6 == HI6_SWC1) {
3357     cpnr = 1;
3358     switch (hi6) {
3359     case HI6_SWC3: cpnr++; /* fallthrough */
3360     case HI6_SWC2: cpnr++;
3361     case HI6_SDC1:
3362     case HI6_SWC1: if (cpu->cd.mips.coproc[cpnr] == NULL ||
3363     (!(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ) {
3364     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3365     cpnr = -1;
3366     break;
3367     } else {
3368     /* Special handling of 64-bit stores
3369     on 32-bit CPUs, and on newer CPUs
3370     in 32-bit compatiblity mode: */
3371     if ((hi6==HI6_SDC1 || hi6==HI6_SDC2) &&
3372     (cpu->cd.mips.cpu_type.isa_level <= 2 ||
3373     !(cp0->reg[COP0_STATUS] & STATUS_FR))) {
3374     uint64_t a, b;
3375     coproc_register_read(cpu,
3376     cpu->cd.mips.coproc[cpnr], rt, &a);
3377     coproc_register_read(cpu,
3378     cpu->cd.mips.coproc[cpnr], rt^1, &b);
3379     if (rt & 1)
3380     fatal("WARNING: SDCx in 32-bit mode from odd register!\n");
3381     value = (a & 0xffffffffULL)
3382     | (b << 32);
3383     } else
3384     coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr], rt, &value);
3385     }
3386     break;
3387     default:
3388     ;
3389     }
3390     if (cpnr < 0)
3391     break;
3392     } else
3393     value = cpu->cd.mips.gpr[rt];
3394    
3395     if (wlen == 4) {
3396     /* Special case for 32-bit stores... (perhaps not worth it) */
3397     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
3398     d[0] = value & 0xff; d[1] = (value >> 8) & 0xff;
3399     d[2] = (value >> 16) & 0xff; d[3] = (value >> 24) & 0xff;
3400     } else {
3401     d[3] = value & 0xff; d[2] = (value >> 8) & 0xff;
3402     d[1] = (value >> 16) & 0xff; d[0] = (value >> 24) & 0xff;
3403     }
3404     } else if (wlen == 16) {
3405     value_hi = cpu->cd.mips.gpr_quadhi[rt];
3406     /* Special case for R5900 128-bit stores: */
3407     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3408     for (i=0; i<8; i++) {
3409     d[i] = (value >> (i*8)) & 255;
3410     d[i+8] = (value_hi >> (i*8)) & 255;
3411     }
3412     else
3413     for (i=0; i<8; i++) {
3414     d[i] = (value >> ((wlen-1-i)*8)) & 255;
3415     d[i + 8] = (value_hi >> ((wlen-1-i)*8)) & 255;
3416     }
3417     } else if (wlen == 1) {
3418     d[0] = value & 0xff;
3419     } else {
3420     /* General case: */
3421     uint64_t v = value;
3422     if (cpu->byte_order ==
3423     EMUL_LITTLE_ENDIAN)
3424     for (i=0; i<wlen; i++) {
3425     d[i] = v & 255;
3426     v >>= 8;
3427     }
3428     else
3429     for (i=0; i<wlen; i++) {
3430     d[wlen-1-i] = v & 255;
3431     v >>= 8;
3432     }
3433     }
3434    
3435     success = cpu->memory_rw(cpu, cpu->mem, addr,
3436     d, wlen, MEM_WRITE, CACHE_DATA);
3437     if (!success) {
3438     /* The store failed, and might have caused an exception. */
3439     if (instruction_trace_cached)
3440     debug("(failed)]\n");
3441     break;
3442     }
3443     } else {
3444     /* load: */
3445     int cpnr = 1;
3446     int success;
3447    
3448     success = cpu->memory_rw(cpu, cpu->mem, addr,
3449     d, wlen, MEM_READ, CACHE_DATA);
3450     if (!success) {
3451     /* The load failed, and might have caused an exception. */
3452     if (instruction_trace_cached)
3453     debug("(failed)]\n");
3454     break;
3455     }
3456    
3457     if (wlen == 1)
3458     value = d[0] | (signd && (d[0]&128)? (-1 << 8) : 0);
3459     else if (wlen != 16) {
3460     /* General case (except for 128-bit): */
3461     int i;
3462     value = 0;
3463     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
3464     if (signd && (d[wlen-1] & 128)!=0) /* sign extend */
3465     value = -1;
3466     for (i=wlen-1; i>=0; i--) {
3467     value <<= 8;
3468     value += d[i];
3469     }
3470     } else {
3471     if (signd && (d[0] & 128)!=0) /* sign extend */
3472     value = -1;
3473     for (i=0; i<wlen; i++) {
3474     value <<= 8;
3475     value += d[i];
3476     }
3477     }
3478     } else {
3479     /* R5900 128-bit quadword: */
3480     int i;
3481     value_hi = 0;
3482     value = 0;
3483     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
3484     for (i=wlen-1; i>=0; i--) {
3485     value_hi <<= 8;
3486     value_hi += (value >> 56) & 255;
3487     value <<= 8;
3488     value += d[i];
3489     }
3490     } else {
3491     for (i=0; i<wlen; i++) {
3492     value_hi <<= 8;
3493     value_hi += (value >> 56) & 255;
3494     value <<= 8;
3495     value += d[i];
3496     }
3497     }
3498     cpu->cd.mips.gpr_quadhi[rt] = value_hi;
3499     }
3500    
3501     switch (hi6) {
3502     case HI6_LWC3: cpnr++; /* fallthrough */
3503     case HI6_LDC2:
3504     case HI6_LWC2: cpnr++;
3505     case HI6_LDC1:
3506     case HI6_LWC1: if (cpu->cd.mips.coproc[cpnr] == NULL ||
3507     (!(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ) {
3508     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3509     } else {
3510     /* Special handling of 64-bit loads
3511     on 32-bit CPUs, and on newer CPUs
3512     in 32-bit compatiblity mode: */
3513     if ((hi6==HI6_LDC1 || hi6==HI6_LDC2) &&
3514     (cpu->cd.mips.cpu_type.isa_level <= 2 ||
3515     !(cp0->reg[COP0_STATUS] & STATUS_FR))) {
3516     uint64_t a, b;
3517     a = (int64_t)(int32_t) (value & 0xffffffffULL);
3518     b = (int64_t)(int32_t) (value >> 32);
3519     coproc_register_write(cpu,
3520     cpu->cd.mips.coproc[cpnr], rt, &a,
3521     hi6==HI6_LDC1 || hi6==HI6_LDC2);
3522     coproc_register_write(cpu,
3523     cpu->cd.mips.coproc[cpnr], rt ^ 1, &b,
3524     hi6==HI6_LDC1 || hi6==HI6_LDC2);
3525     if (rt & 1)
3526     fatal("WARNING: LDCx in 32-bit mode to odd register!\n");
3527     } else {
3528     coproc_register_write(cpu,
3529     cpu->cd.mips.coproc[cpnr], rt, &value,
3530     hi6==HI6_LDC1 || hi6==HI6_LDC2);
3531     }
3532     }
3533     break;
3534     default: if (rt != 0)
3535     cpu->cd.mips.gpr[rt] = value;
3536     }
3537     }
3538    
3539     if (linked && st==1) {
3540     /*
3541     * The store succeeded. Invalidate any other
3542     * cpu's store to this cache line, and then
3543     * return 1 in gpr rt:
3544     *
3545     * (this is a semi-ugly hack using global
3546     * 'cpus')
3547     *
3548     * TODO: How about invalidating other CPUs
3549     * stores to this cache line, even if this
3550     * was _NOT_ a linked store?
3551     */
3552     for (i=0; i<cpu->machine->ncpus; i++) {
3553     if (cpu->machine->cpus[i]->cd.mips.rmw) {
3554     uint64_t yaddr = addr;
3555     uint64_t xaddr =
3556     cpu->machine->cpus[i]->cd.mips.rmw_addr;
3557     uint64_t mask;
3558     mask = ~(cpu->machine->cpus[i]->
3559     cd.mips.cache_linesize[CACHE_DATA]
3560     - 1);
3561     xaddr &= mask;
3562     yaddr &= mask;
3563     if (xaddr == yaddr) {
3564     cpu->machine->cpus[i]->cd.mips.rmw = 0;
3565     cpu->machine->cpus[i]->cd.mips.rmw_addr = 0;
3566     }
3567     }
3568     }
3569    
3570     if (rt != 0)
3571     cpu->cd.mips.gpr[rt] = 1;
3572    
3573     if (instruction_trace_cached)
3574     debug(" [no collision] ");
3575     cpu->cd.mips.rmw = 0;
3576     }
3577    
3578     if (instruction_trace_cached) {
3579     switch (wlen) {
3580     case 2: debug("0x%04x", (int)value); break;
3581     case 4: debug("0x%08x", (int)value); break;
3582     case 8: debug("0x%016llx", (long long)value);
3583     break;
3584     case 16:debug("0x%016llx", (long long)value_hi);
3585     debug("%016llx", (long long)value);
3586     break;
3587     default:debug("0x%02x", (int)value);
3588     }
3589     debug("]\n");
3590     }
3591     return 1;
3592     case HI6_LWL: /* Unaligned load/store */
3593     case HI6_LWR:
3594     case HI6_LDL:
3595     case HI6_LDR:
3596     case HI6_SWL:
3597     case HI6_SWR:
3598     case HI6_SDL:
3599     case HI6_SDR:
3600     /* For L (Left): address is the most significant byte */
3601     /* For R (Right): address is the least significant byte */
3602     addr = cpu->cd.mips.gpr[rs] + imm;
3603    
3604     is_left = 0;
3605     if (hi6 == HI6_SWL || hi6 == HI6_LWL ||
3606     hi6 == HI6_SDL || hi6 == HI6_LDL)
3607     is_left = 1;
3608    
3609     wlen = 0; st = 0;
3610     signd = 0;
3611     if (hi6 == HI6_LWL || hi6 == HI6_LWR)
3612     signd = 1;
3613    
3614     if (hi6 == HI6_LWL || hi6 == HI6_LWR) { wlen = 4; st = 0; }
3615     if (hi6 == HI6_SWL || hi6 == HI6_SWR) { wlen = 4; st = 1; }
3616     if (hi6 == HI6_LDL || hi6 == HI6_LDR) { wlen = 8; st = 0; }
3617     if (hi6 == HI6_SDL || hi6 == HI6_SDR) { wlen = 8; st = 1; }
3618    
3619     dir = 1; /* big endian, Left */
3620     reg_dir = -1;
3621     reg_ofs = wlen - 1; /* byte offset in the register */
3622     if (!is_left) {
3623     dir = -dir;
3624     reg_ofs = 0;
3625     reg_dir = 1;
3626     }
3627     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3628     dir = -dir;
3629    
3630     result_value = cpu->cd.mips.gpr[rt];
3631    
3632     if (st) {
3633     /* Store: */
3634     uint64_t aligned_addr = addr & ~(wlen-1);
3635     unsigned char aligned_word[8];
3636     uint64_t oldpc = cpu->pc;
3637     /*
3638     * NOTE (this is ugly): The memory_rw()
3639     * call generates a TLBL exception, if there
3640     * is a tlb refill exception. However, since
3641     * this is a Store, the exception is converted
3642     * to a TLBS:
3643     */
3644     int ok = cpu->memory_rw(cpu, cpu->mem,
3645     aligned_addr, &aligned_word[0], wlen,
3646     MEM_READ, CACHE_DATA);
3647     if (!ok) {
3648     if (cpu->pc != oldpc) {
3649     cp0->reg[COP0_CAUSE] &= ~CAUSE_EXCCODE_MASK;
3650     cp0->reg[COP0_CAUSE] |= (EXCEPTION_TLBS << CAUSE_EXCCODE_SHIFT);
3651     }
3652     return 1;
3653     }
3654    
3655     for (i=0; i<wlen; i++) {
3656     tmpaddr = addr + i*dir;
3657     /* Have we moved into another word/dword? Then stop: */
3658     if ( (tmpaddr & ~(wlen-1)) != (addr & ~(wlen-1)) )
3659     break;
3660    
3661     /* debug("unaligned byte at %016llx, reg_ofs=%i reg=0x%016llx\n",
3662     tmpaddr, reg_ofs, (long long)result_value); */
3663    
3664     /* Store one byte: */
3665     aligned_word[tmpaddr & (wlen-1)] = (result_value >> (reg_ofs * 8)) & 255;
3666    
3667     reg_ofs += reg_dir;
3668     }
3669    
3670     ok = cpu->memory_rw(cpu, cpu->mem,
3671     aligned_addr, &aligned_word[0], wlen,
3672     MEM_WRITE, CACHE_DATA);
3673     if (!ok)
3674     return 1;
3675     } else {
3676     /* Load: */
3677     uint64_t aligned_addr = addr & ~(wlen-1);
3678     unsigned char aligned_word[8], databyte;
3679     int ok = cpu->memory_rw(cpu, cpu->mem,
3680     aligned_addr, &aligned_word[0], wlen,
3681     MEM_READ, CACHE_DATA);
3682     if (!ok)
3683     return 1;
3684    
3685     for (i=0; i<wlen; i++) {
3686     tmpaddr = addr + i*dir;
3687     /* Have we moved into another word/dword? Then stop: */
3688     if ( (tmpaddr & ~(wlen-1)) != (addr & ~(wlen-1)) )
3689     break;
3690    
3691     /* debug("unaligned byte at %016llx, reg_ofs=%i reg=0x%016llx\n",
3692     tmpaddr, reg_ofs, (long long)result_value); */
3693    
3694     /* Load one byte: */
3695     databyte = aligned_word[tmpaddr & (wlen-1)];
3696     result_value &= ~((uint64_t)0xff << (reg_ofs * 8));
3697     result_value |= (uint64_t)databyte << (reg_ofs * 8);
3698    
3699     reg_ofs += reg_dir;
3700     }
3701    
3702     if (rt != 0)
3703     cpu->cd.mips.gpr[rt] = result_value;
3704     }
3705    
3706     /* Sign extend for 32-bit load lefts: */
3707     if (!st && signd && wlen == 4) {
3708     cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
3709     if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
3710     cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
3711     }
3712    
3713     if (instruction_trace_cached) {
3714     char *t;
3715     switch (wlen) {
3716     case 2: t = "0x%04llx"; break;
3717     case 4: t = "0x%08llx"; break;
3718     case 8: t = "0x%016llx"; break;
3719     default: t = "0x%02llx";
3720     }
3721     debug(t, (long long)cpu->cd.mips.gpr[rt]);
3722     debug("]\n");
3723     }
3724    
3725     return 1;
3726     }
3727     return 1;
3728     case HI6_REGIMM:
3729     regimm5 = instr[2] & 0x1f;
3730    
3731     if (show_opcode_statistics)
3732     cpu->cd.mips.stats__regimm[regimm5] ++;
3733    
3734     switch (regimm5) {
3735     case REGIMM_BLTZ:
3736     case REGIMM_BGEZ:
3737     case REGIMM_BLTZL:
3738     case REGIMM_BGEZL:
3739     case REGIMM_BLTZAL:
3740     case REGIMM_BLTZALL:
3741     case REGIMM_BGEZAL:
3742     case REGIMM_BGEZALL:
3743     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3744     imm = (instr[1] << 8) + instr[0];
3745     if (imm >= 32768) /* signed 16-bit */
3746     imm -= 65536;
3747    
3748     cond = and_link = likely = 0;
3749    
3750     switch (regimm5) {
3751     case REGIMM_BLTZL: likely = 1;
3752     case REGIMM_BLTZ: cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) != 0;
3753     break;
3754     case REGIMM_BGEZL: likely = 1;
3755     case REGIMM_BGEZ: cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) == 0;
3756     break;
3757    
3758     case REGIMM_BLTZALL: likely = 1;
3759     case REGIMM_BLTZAL: and_link = 1;
3760     cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) != 0;
3761     break;
3762     case REGIMM_BGEZALL: likely = 1;
3763     case REGIMM_BGEZAL: and_link = 1;
3764     cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) == 0;
3765     break;
3766     }
3767    
3768     if (and_link)
3769     cpu->cd.mips.gpr[31] = cached_pc + 4;
3770    
3771     if (cond) {
3772     cpu->cd.mips.delay_slot = TO_BE_DELAYED;
3773     cpu->cd.mips.delay_jmpaddr = cached_pc + (imm << 2);
3774     } else {
3775     if (likely)
3776     cpu->cd.mips.nullify_next = 1; /* nullify delay slot */
3777     }
3778    
3779     return 1;
3780     default:
3781     if (!instruction_trace_cached) {
3782     fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
3783     cpu->cpu_id, cpu->cd.mips.pc_last,
3784     instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
3785     }
3786     fatal("unimplemented regimm5 = 0x%02x\n", regimm5);
3787     cpu->running = 0;
3788     return 1;
3789     }
3790     /* NOT REACHED */
3791     case HI6_J:
3792     case HI6_JAL:
3793     if (cpu->cd.mips.delay_slot) {
3794     fatal("j/jal: jump inside a jump's delay slot, or similar. TODO\n");
3795     cpu->running = 0;
3796     return 1;
3797     }
3798     imm = ((instr[3] & 3) << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3799     imm <<= 2;
3800    
3801     if (hi6 == HI6_JAL)
3802     cpu->cd.mips.gpr[31] = cached_pc + 4; /* pc already increased by 4 earlier */
3803    
3804     addr = cached_pc & ~((1 << 28) - 1);
3805     addr |= imm;
3806    
3807     cpu->cd.mips.delay_slot = TO_BE_DELAYED;
3808     cpu->cd.mips.delay_jmpaddr = addr;
3809    
3810     if (!quiet_mode_cached && cpu->machine->show_trace_tree &&
3811     hi6 == HI6_JAL) {
3812     cpu->cd.mips.show_trace_delay = 2;
3813     cpu->cd.mips.show_trace_addr = addr;
3814     }
3815    
3816     return 1;
3817     case HI6_COP0:
3818     case HI6_COP1:
3819     case HI6_COP2:
3820     case HI6_COP3:
3821     imm = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3822     imm &= ((1 << 26) - 1);
3823    
3824     cpnr = 0;
3825     if (hi6 == HI6_COP0) cpnr = 0;
3826     if (hi6 == HI6_COP1) cpnr = 1;
3827     if (hi6 == HI6_COP2) cpnr = 2;
3828     if (hi6 == HI6_COP3) cpnr = 3;
3829    
3830     /*
3831     * If there is no coprocessor nr cpnr, or we are running in
3832     * userland and the coprocessor is not marked as Useable in
3833     * the status register of CP0, then we get an exception.
3834     *
3835     * An exception (hehe) to this rule is that the kernel should
3836     * always be able to access CP0.
3837     */
3838     /* Set tmp = 1 if we're in user mode. */
3839     tmp = 0;
3840     switch (cpu->cd.mips.cpu_type.exc_model) {
3841     case EXC3K:
3842     /*
3843     * NOTE: If the KU bit is checked, Linux crashes.
3844     * It is the PC that counts. TODO: Check whether
3845     * this is true or not for R4000 as well.
3846     */
3847     if (cached_pc <= 0x7fffffff) /* if (cp0->reg[COP0_STATUS] & MIPS1_SR_KU_CUR) */
3848     tmp = 1;
3849     break;
3850     default:
3851     /* R4000 etc: (TODO: How about supervisor mode?) */
3852     if (((cp0->reg[COP0_STATUS] & STATUS_KSU_MASK) >> STATUS_KSU_SHIFT) != KSU_KERNEL)
3853     tmp = 1;
3854     if (cp0->reg[COP0_STATUS] & STATUS_ERL)
3855     tmp = 0;
3856     if (cp0->reg[COP0_STATUS] & STATUS_EXL)
3857     tmp = 0;
3858     break;
3859     }
3860     if (cpu->cd.mips.coproc[cpnr] == NULL ||
3861     (tmp && !(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ||
3862     (!tmp && cpnr >= 1 && !(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)))
3863     ) {
3864     if (instruction_trace_cached)
3865     debug("cop%i\t0x%08x => coprocessor unusable\n", cpnr, (int)imm);
3866    
3867     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3868     } else {
3869     /*
3870     * Execute the coprocessor function. The
3871     * coproc_function code outputs instruction
3872     * trace, if necessary.
3873     */
3874     coproc_function(cpu, cpu->cd.mips.coproc[cpnr],
3875     cpnr, imm, 0, 1);
3876     }
3877     return 1;
3878     case HI6_CACHE:
3879     rt = ((instr[3] & 3) << 3) + (instr[2] >> 5); /* base */
3880     copz = instr[2] & 31;
3881     imm = (instr[1] << 8) + instr[0];
3882    
3883     cache_op = copz >> 2;
3884     which_cache = copz & 3;
3885    
3886     /*
3887     * TODO: The cache instruction is implementation dependant.
3888     * This is really ugly.
3889     */
3890    
3891     #if 0
3892     Remove this...
3893    
3894     /* if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) { */
3895     /* printf("taghi=%08lx taglo=%08lx\n",
3896     (long)cp0->reg[COP0_TAGDATA_HI],
3897     (long)cp0->reg[COP0_TAGDATA_LO]);
3898     */
3899     if (cp0->reg[COP0_TAGDATA_HI] == 0 &&
3900     cp0->reg[COP0_TAGDATA_LO] == 0) {
3901     /* Normal cache operation: */
3902     cpu->r10k_cache_disable_TODO = 0;
3903     } else {
3904     /* Dislocate the cache: */
3905     cpu->r10k_cache_disable_TODO = 1;
3906     }
3907     /* } */
3908     #endif
3909    
3910     /*
3911     * Clear the LLbit (at least on R10000):
3912     * TODO: How about R4000?
3913     */
3914     cpu->cd.mips.rmw = 0;
3915    
3916     return 1;
3917     case HI6_SPECIAL2:
3918     special6 = instr[0] & 0x3f;
3919    
3920     if (show_opcode_statistics)
3921     cpu->cd.mips.stats__special2[special6] ++;
3922    
3923     instrword = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3924    
3925     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3926     rt = instr[2] & 31;
3927     rd = (instr[1] >> 3) & 31;
3928    
3929     /* printf("special2 %08x rs=0x%02x rt=0x%02x rd=0x%02x\n", instrword, rs,rt,rd); */
3930    
3931     /*
3932     * Many of these can be found in the R5000 docs, or figured out
3933     * by studying binutils source code for MIPS instructions.
3934     */
3935    
3936     if ((instrword & 0xfc0007ffULL) == 0x70000000) {
3937     {
3938     int32_t a, b;
3939     int64_t c;
3940     a = (int32_t)cpu->cd.mips.gpr[rs];
3941     b = (int32_t)cpu->cd.mips.gpr[rt];
3942     c = a * b;
3943     c += (cpu->cd.mips.lo & 0xffffffffULL)
3944     + (cpu->cd.mips.hi << 32);
3945     cpu->cd.mips.lo = (int64_t)((int32_t)c);
3946     cpu->cd.mips.hi = (int64_t)((int32_t)(c >> 32));
3947    
3948     /*
3949     * The R5000 manual says that rd should be all zeros,
3950     * but it isn't on R5900. I'm just guessing here that
3951     * it stores the value in register rd, in addition to hi/lo.
3952     * TODO
3953     */
3954     if (rd != 0)
3955     cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
3956     }
3957     } else if ((instrword & 0xffff07ffULL) == 0x70000209
3958     || (instrword & 0xffff07ffULL) == 0x70000249) {
3959     /*
3960     * This is just a guess for R5900, I've not found any docs on this one yet.
3961     *
3962     * pmfhi/pmflo rd
3963     *
3964     * If the lowest 8 bits of the instruction word are 0x09, it's a pmfhi.
3965     * If the lowest bits are 0x49, it's a pmflo.
3966     *
3967     * A wild guess is that this is a 128-bit version of mfhi/mflo.
3968     * For now, this is implemented as 64-bit only. (TODO)
3969     */
3970     if (instr[0] == 0x49) {
3971     cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
3972     } else {
3973     cpu->cd.mips.gpr[rd] = cpu->cd.mips.hi;
3974     }
3975     } else if ((instrword & 0xfc1fffff) == 0x70000269 || (instrword & 0xfc1fffff) == 0x70000229) {
3976     /*
3977     * This is just a guess for R5900, I've not found any docs on this one yet.
3978     *
3979     * pmthi/pmtlo rs (pmtlo = 269, pmthi = 229)
3980     *
3981     * A wild guess is that this is a 128-bit version of mthi/mtlo.
3982     * For now, this is implemented as 64-bit only. (TODO)
3983     */
3984     if (instr[0] == 0x69) {
3985     cpu->cd.mips.lo = cpu->cd.mips.gpr[rs];
3986     } else {
3987     cpu->cd.mips.hi = cpu->cd.mips.gpr[rs];
3988     }
3989     } else if ((instrword & 0xfc0007ff) == 0x700004a9) {
3990     /*
3991     * This is just a guess for R5900, I've not found any docs on this one yet.
3992     *
3993     * por dst,src,src2 ==> rs=src rt=src2 rd=dst
3994     *
3995     * A wild guess is that this is a 128-bit "or" between two registers.
3996     * For now, let's just or using 64-bits. (TODO)
3997     */
3998     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt];
3999     } else if ((instrword & 0xfc0007ff) == 0x70000488) {
4000     /*
4001     * R5900 "undocumented" pextlw. TODO: find out if this is correct.
4002     * It seems that this instruction is used to combine two 32-bit
4003     * words into a 64-bit dword, typically before a sd (store dword).
4004     */
4005     cpu->cd.mips.gpr[rd] =
4006     ((cpu->cd.mips.gpr[rs] & 0xffffffffULL) << 32) /* TODO: switch rt and rs? */
4007     | (cpu->cd.mips.gpr[rt] & 0xffffffffULL);
4008     } else if (special6 == SPECIAL2_MUL) {
4009     cpu->cd.mips.gpr[rd] = (int64_t)cpu->cd.mips.gpr[rt] *
4010     (int64_t)cpu->cd.mips.gpr[rs];
4011     } else if (special6 == SPECIAL2_CLZ) {
4012     /* clz: count leading zeroes */
4013     int i, n=0;
4014     for (i=31; i>=0; i--) {
4015     if (cpu->cd.mips.gpr[rs] & ((uint32_t)1 << i))
4016     break;
4017     else
4018     n++;
4019     }
4020     cpu->cd.mips.gpr[rd] = n;
4021     } else if (special6 == SPECIAL2_CLO) {
4022     /* clo: count leading ones */
4023     int i, n=0;
4024     for (i=31; i>=0; i--) {
4025     if (cpu->cd.mips.gpr[rs] & ((uint32_t)1 << i))
4026     n++;
4027     else
4028     break;
4029     }
4030     cpu->cd.mips.gpr[rd] = n;
4031     } else if (special6 == SPECIAL2_DCLZ) {
4032     /* dclz: count leading zeroes */
4033     int i, n=0;
4034     for (i=63; i>=0; i--) {
4035     if (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << i))
4036     break;
4037     else
4038     n++;
4039     }
4040     cpu->cd.mips.gpr[rd] = n;
4041     } else if (special6 == SPECIAL2_DCLO) {
4042     /* dclo: count leading ones */
4043     int i, n=0;
4044     for (i=63; i>=0; i--) {
4045     if (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << i))
4046     n++;
4047     else
4048     break;
4049     }
4050     cpu->cd.mips.gpr[rd] = n;
4051     } else {
4052     if (!instruction_trace_cached) {
4053     fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
4054     cpu->cpu_id, cpu->cd.mips.pc_last,
4055     instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
4056     }
4057     fatal("unimplemented special_2 = 0x%02x, rs=0x%02x rt=0x%02x rd=0x%02x\n",
4058     special6, rs, rt, rd);
4059     cpu->running = 0;
4060     return 1;
4061     }
4062     return 1;
4063     default:
4064     if (!instruction_trace_cached) {
4065     fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
4066     cpu->cpu_id, cpu->cd.mips.pc_last,
4067     instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
4068     }
4069     fatal("unimplemented hi6 = 0x%02x\n", hi6);
4070     cpu->running = 0;
4071     return 1;
4072     }
4073    
4074     /* NOTREACHED */
4075     }
4076    
4077    
4078     #define CPU_RUN mips_cpu_run
4079     #define CPU_RUN_MIPS
4080     #define CPU_RINSTR mips_cpu_run_instr
4081     #include "cpu_run.c"
4082     #undef CPU_RINSTR
4083     #undef CPU_RUN_MIPS
4084     #undef CPU_RUN
4085    
4086    
4087     /*
4088     * mips_cpu_dumpinfo():
4089     *
4090     * Debug dump of MIPS-specific CPU data for specific CPU.
4091     */
4092     void mips_cpu_dumpinfo(struct cpu *cpu)
4093     {
4094     struct mips_cpu_type_def *ct = &cpu->cd.mips.cpu_type;
4095    
4096     debug(" (%i-bit ", (ct->isa_level < 3 ||
4097     ct->isa_level == 32)? 32 : 64);
4098    
4099     debug("%s, ", cpu->byte_order == EMUL_BIG_ENDIAN? "BE" : "LE");
4100    
4101     debug("nTLB=%i", ct->nr_of_tlb_entries);
4102    
4103     if (ct->default_picache || ct->default_pdcache)
4104     debug(", I+D = %i+%i KB",
4105     (1 << ct->default_picache) / 1024,
4106     (1 << ct->default_pdcache) / 1024);
4107    
4108     if (ct->default_scache) {
4109     int kb = (1 << ct->default_scache) / 1024;
4110     debug(", L2 = %i %cB",
4111     kb >= 1024? kb / 1024 : kb,
4112     kb >= 1024? 'M' : 'K');
4113     }
4114    
4115     debug(")\n");
4116     }
4117    
4118    
4119     /*
4120     * mips_cpu_list_available_types():
4121     *
4122     * Print a list of available MIPS CPU types.
4123     */
4124     void mips_cpu_list_available_types(void)
4125     {
4126     int i, j;
4127     struct mips_cpu_type_def cpu_type_defs[] = MIPS_CPU_TYPE_DEFS;
4128    
4129     i = 0;
4130     while (cpu_type_defs[i].name != NULL) {
4131     debug("%s", cpu_type_defs[i].name);
4132     for (j=10 - strlen(cpu_type_defs[i].name); j>0; j--)
4133     debug(" ");
4134     i++;
4135     if ((i % 6) == 0 || cpu_type_defs[i].name == NULL)
4136     debug("\n");
4137     }
4138     }
4139    
4140    
4141     /*
4142     * mips_cpu_family_init():
4143     *
4144     * Fill in the cpu_family struct for MIPS.
4145     */
4146     int mips_cpu_family_init(struct cpu_family *fp)
4147     {
4148     fp->name = "MIPS";
4149     fp->cpu_new = mips_cpu_new;
4150     fp->list_available_types = mips_cpu_list_available_types;
4151     fp->register_match = mips_cpu_register_match;
4152     fp->disassemble_instr = mips_cpu_disassemble_instr;
4153     fp->register_dump = mips_cpu_register_dump;
4154     fp->run = mips_cpu_run;
4155     fp->dumpinfo = mips_cpu_dumpinfo;
4156     fp->show_full_statistics = mips_cpu_show_full_statistics;
4157     fp->tlbdump = mips_cpu_tlbdump;
4158     fp->interrupt = mips_cpu_interrupt;
4159     fp->interrupt_ack = mips_cpu_interrupt_ack;
4160     return 1;
4161     }
4162    
4163    
4164     #endif /* ENABLE_MIPS */

  ViewVC Help
Powered by ViewVC 1.1.26