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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations)
Mon Oct 8 16:17:48 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 74915 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_coproc.c,v 1.11 2005/03/15 06:52:14 debug Exp $
29     *
30     * Emulation of MIPS coprocessors.
31     */
32    
33     #include <stdio.h>
34     #include <stdlib.h>
35     #include <string.h>
36     #include <math.h>
37    
38     #include "bintrans.h"
39     #include "cop0.h"
40     #include "cpu.h"
41     #include "cpu_mips.h"
42     #include "emul.h"
43     #include "machine.h"
44     #include "memory.h"
45     #include "mips_cpu_types.h"
46     #include "misc.h"
47     #include "opcodes_mips.h"
48    
49    
50     #ifndef ENABLE_MIPS
51    
52    
53     struct mips_coproc *mips_coproc_new(struct cpu *cpu, int coproc_nr)
54     { return NULL; }
55    
56     void mips_coproc_tlb_set_entry(struct cpu *cpu, int entrynr, int size,
57     uint64_t vaddr, uint64_t paddr0, uint64_t paddr1,
58     int valid0, int valid1, int dirty0, int dirty1, int global, int asid,
59     int cachealgo0, int cachealgo1) { }
60    
61    
62     #else /* ENABLE_MIPS */
63    
64    
65     extern volatile int single_step;
66    
67     static char *cop0_names[] = COP0_NAMES;
68     static char *regnames[] = MIPS_REGISTER_NAMES;
69    
70    
71     /* FPU control registers: */
72     #define FPU_FCIR 0
73     #define FPU_FCCR 25
74     #define FPU_FCSR 31
75     #define FCSR_FCC0_SHIFT 23
76     #define FCSR_FCC1_SHIFT 25
77    
78    
79     /*
80     * initialize_cop0_config():
81     *
82     * Helper function, called from mips_coproc_new().
83     */
84     static void initialize_cop0_config(struct cpu *cpu, struct mips_coproc *c)
85     {
86     #ifdef ENABLE_MIPS16
87     const int m16 = 1;
88     #else
89     const int m16 = 0;
90     #endif
91     int IB, DB, SB, IC, DC, SC;
92    
93     /* Default values: */
94     c->reg[COP0_CONFIG] =
95     ( 0 << 31) /* config1 present */
96     | (0x00 << 16) /* implementation dependant */
97     | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
98     /* endian mode */
99     | ( 2 << 13) /* 0 = MIPS32,
100     1 = MIPS64 with 32-bit segments,
101     2 = MIPS64 with all segments,
102     3 = reserved */
103     | ( 0 << 10) /* architecture revision level,
104     0 = "Revision 1", other
105     values are reserved */
106     | ( 1 << 7) /* MMU type: 0 = none,
107     1 = Standard TLB,
108     2 = Standard BAT,
109     3 = fixed mapping, 4-7=reserved */
110     | ( 0 << 0) /* kseg0 coherency algorithm
111     (TODO) */
112     ;
113    
114     switch (cpu->cd.mips.cpu_type.rev) {
115     case MIPS_R4000: /* according to the R4000 manual */
116     case MIPS_R4600:
117     IB = cpu->machine->cache_picache_linesize - 4;
118     IB = IB < 0? 0 : (IB > 1? 1 : IB);
119     DB = cpu->machine->cache_pdcache_linesize - 4;
120     DB = DB < 0? 0 : (DB > 1? 1 : DB);
121     SB = cpu->machine->cache_secondary_linesize - 4;
122     SB = SB < 0? 0 : (SB > 3? 3 : SB);
123     IC = cpu->machine->cache_picache - 12;
124     IC = IC < 0? 0 : (IC > 7? 7 : IC);
125     DC = cpu->machine->cache_pdcache - 12;
126     DC = DC < 0? 0 : (DC > 7? 7 : DC);
127     SC = cpu->machine->cache_secondary? 0 : 1;
128     c->reg[COP0_CONFIG] =
129     ( 0 << 31) /* Master/Checker present bit */
130     | (0x00 << 28) /* EC: system clock divisor,
131     0x00 = '2' */
132     | (0x00 << 24) /* EP */
133     | ( SB << 22) /* SB */
134     | (0x00 << 21) /* SS: 0 = mixed i/d scache */
135     | (0x00 << 20) /* SW */
136     | (0x00 << 18) /* EW: 0=64-bit */
137     | ( SC << 17) /* SC: 0=secondary cache present,
138     1=non-present */
139     | (0x00 << 16) /* SM: (todo) */
140     | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
141     /* endian mode */
142     | (0x01 << 14) /* ECC: 0=enabled, 1=disabled */
143     | (0x00 << 13) /* EB: (todo) */
144     | (0x00 << 12) /* 0 (resered) */
145     | ( IC << 9) /* IC: I-cache = 2^(12+IC) bytes
146     (1 = 8KB, 4=64K) */
147     | ( DC << 6) /* DC: D-cache = 2^(12+DC) bytes
148     (1 = 8KB, 4=64K) */
149     | ( IB << 5) /* IB: I-cache line size (0=16,
150     1=32) */
151     | ( DB << 4) /* DB: D-cache line size (0=16,
152     1=32) */
153     | ( 0 << 3) /* CU: todo */
154     | ( 0 << 0) /* kseg0 coherency algorithm
155     (TODO) */
156     ;
157     break;
158     case MIPS_R4100: /* According to the VR4131 manual: */
159     IB = cpu->machine->cache_picache_linesize - 4;
160     IB = IB < 0? 0 : (IB > 1? 1 : IB);
161     DB = cpu->machine->cache_pdcache_linesize - 4;
162     DB = DB < 0? 0 : (DB > 1? 1 : DB);
163     IC = cpu->machine->cache_picache - 10;
164     IC = IC < 0? 0 : (IC > 7? 7 : IC);
165     DC = cpu->machine->cache_pdcache - 10;
166     DC = DC < 0? 0 : (DC > 7? 7 : DC);
167     c->reg[COP0_CONFIG] =
168     ( 0 << 31) /* IS: Instruction Streaming bit */
169     | (0x01 << 28) /* EC: system clock divisor,
170     0x01 = 2 */
171     | (0x00 << 24) /* EP */
172     | (0x00 << 23) /* AD: Accelerate data mode
173     (0=VR4000-compatible) */
174     | ( m16 << 20) /* M16: MIPS16 support */
175     | ( 1 << 17) /* '1' */
176     | (0x00 << 16) /* BP: 'Branch forecast'
177     (0 = enabled) */
178     | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
179     /* endian mode */
180     | ( 2 << 13) /* '2' hardcoded on VR4131 */
181     | ( 1 << 12) /* CS: Cache size mode
182     (1 on VR4131) */
183     | ( IC << 9) /* IC: I-cache = 2^(10+IC) bytes
184     (0 = 1KB, 4=16K) */
185     | ( DC << 6) /* DC: D-cache = 2^(10+DC) bytes
186     (0 = 1KB, 4=16K) */
187     | ( IB << 5) /* IB: I-cache line size (0=16,
188     1=32) */
189     | ( DB << 4) /* DB: D-cache line size (0=16,
190     1=32) */
191     | ( 0 << 0) /* kseg0 coherency algorithm (TODO) */
192     ;
193     break;
194     case MIPS_R5000:
195     case MIPS_RM5200: /* rm5200 is just a wild guess */
196     /* These are just guesses: (the comments are wrong) */
197     c->reg[COP0_CONFIG] =
198     ( 0 << 31) /* Master/Checker present bit */
199     | (0x00 << 28) /* EC: system clock divisor,
200     0x00 = '2' */
201     | (0x00 << 24) /* EP */
202     | (0x00 << 22) /* SB */
203     | (0x00 << 21) /* SS */
204     | (0x00 << 20) /* SW */
205     | (0x00 << 18) /* EW: 0=64-bit */
206     | (0x01 << 17) /* SC: 0=secondary cache present,
207     1=non-present */
208     | (0x00 << 16) /* SM: (todo) */
209     | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
210     /* endian mode */
211     | (0x01 << 14) /* ECC: 0=enabled, 1=disabled */
212     | (0x00 << 13) /* EB: (todo) */
213     | (0x00 << 12) /* 0 (resered) */
214     | ( 3 << 9) /* IC: I-cache = 2^(12+IC) bytes
215     (1 = 8KB, 4=64K) */
216     | ( 3 << 6) /* DC: D-cache = 2^(12+DC) bytes
217     (1 = 8KB, 4=64K) */
218     | ( 1 << 5) /* IB: I-cache line size (0=16,
219     1=32) */
220     | ( 1 << 4) /* DB: D-cache line size (0=16,
221     1=32) */
222     | ( 0 << 3) /* CU: todo */
223     | ( 2 << 0) /* kseg0 coherency algorithm
224     (TODO) */
225     ;
226     break;
227     case MIPS_R10000:
228     case MIPS_R12000:
229     case MIPS_R14000:
230     IC = cpu->machine->cache_picache - 12;
231     IC = IC < 0? 0 : (IC > 7? 7 : IC);
232     DC = cpu->machine->cache_pdcache - 12;
233     DC = DC < 0? 0 : (DC > 7? 7 : DC);
234     SC = cpu->machine->cache_secondary - 19;
235     SC = SC < 0? 0 : (SC > 7? 7 : SC);
236     /* According to the R10000 User's Manual: */
237     c->reg[COP0_CONFIG] =
238     ( IC << 29) /* Primary instruction cache size
239     (3 = 32KB) */
240     | ( DC << 26) /* Primary data cache size (3 =
241     32KB) */
242     | ( 0 << 19) /* SCClkDiv */
243     | ( SC << 16) /* SCSize, secondary cache size.
244     0 = 512KB. powers of two */
245     | ( 0 << 15) /* MemEnd */
246     | ( 0 << 14) /* SCCorEn */
247     | ( 1 << 13) /* SCBlkSize. 0=16 words,
248     1=32 words */
249     | ( 0 << 9) /* SysClkDiv */
250     | ( 0 << 7) /* PrcReqMax */
251     | ( 0 << 6) /* PrcElmReq */
252     | ( 0 << 5) /* CohPrcReqTar */
253     | ( 0 << 3) /* Device number */
254     | ( 2 << 0) /* Cache coherency algorithm for
255     kseg0 */
256     ;
257     break;
258     case MIPS_R5900:
259     /*
260     * R5900 is supposed to have the following (according
261     * to NetBSD/playstation2):
262     * cpu0: 16KB/64B 2-way set-associative L1 Instruction
263     * cache, 48 TLB entries
264     * cpu0: 8KB/64B 2-way set-associative write-back L1
265     * Data cache
266     * The following settings are just guesses:
267     * (comments are incorrect)
268     */
269     c->reg[COP0_CONFIG] =
270     ( 0 << 31) /* Master/Checker present bit */
271     | (0x00 << 28) /* EC: system clock divisor,
272     0x00 = '2' */
273     | (0x00 << 24) /* EP */
274     | (0x00 << 22) /* SB */
275     | (0x00 << 21) /* SS */
276     | (0x00 << 20) /* SW */
277     | (0x00 << 18) /* EW: 0=64-bit */
278     | (0x01 << 17) /* SC: 0=secondary cache present,
279     1=non-present */
280     | (0x00 << 16) /* SM: (todo) */
281     | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
282     /* endian mode */
283     | (0x01 << 14) /* ECC: 0=enabled, 1=disabled */
284     | (0x00 << 13) /* EB: (todo) */
285     | (0x00 << 12) /* 0 (resered) */
286     | ( 3 << 9) /* IC: I-cache = 2^(12+IC) bytes
287     (1 = 8KB, 4=64K) */
288     | ( 3 << 6) /* DC: D-cache = 2^(12+DC) bytes
289     (1 = 8KB, 4=64K) */
290     | ( 1 << 5) /* IB: I-cache line size (0=16,
291     1=32) */
292     | ( 1 << 4) /* DB: D-cache line size (0=16,
293     1=32) */
294     | ( 0 << 3) /* CU: todo */
295     | ( 0 << 0) /* kseg0 coherency algorithm
296     (TODO) */
297     ;
298     break;
299     case MIPS_4Kc:
300     case MIPS_5Kc:
301     /* According to the MIPS64 5K User's Manual: */
302     /* TODO: How good does this work with 4K? */
303     c->reg[COP0_CONFIG] =
304     ( (uint32_t)1 << 31)/* Config 1 present bit */
305     | ( 0 << 20) /* ISD: instruction scheduling
306     disable (=1) */
307     | ( 0 << 17) /* DID: dual issue disable */
308     | ( 0 << 16) /* BM: burst mode */
309     | ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15)
310     /* endian mode */
311     | ((cpu->cd.mips.cpu_type.rev==MIPS_5Kc?2:1) << 13)
312     /* 1=32-bit only, 2=32/64 */
313     | ( 0 << 10) /* Architecture revision */
314     | ( 1 << 7) /* MMU type: 1=TLB, 3=FMT */
315     | ( 2 << 0) /* kseg0 cache coherency algorithm */
316     ;
317     /* TODO: Config select 1: caches and such */
318     break;
319     default:
320     ;
321     }
322     }
323    
324    
325     /*
326     * initialize_cop1():
327     *
328     * Helper function, called from mips_coproc_new().
329     */
330     static void initialize_cop1(struct cpu *cpu, struct mips_coproc *c)
331     {
332     int fpu_rev;
333     uint64_t other_stuff = 0;
334    
335     switch (cpu->cd.mips.cpu_type.rev & 0xff) {
336     case MIPS_R2000: fpu_rev = MIPS_R2010; break;
337     case MIPS_R3000: fpu_rev = MIPS_R3010;
338     other_stuff |= 0x40; /* or 0x30? TODO */
339     break;
340     case MIPS_R6000: fpu_rev = MIPS_R6010; break;
341     case MIPS_R4000: fpu_rev = MIPS_R4010; break;
342     case MIPS_4Kc: /* TODO: Is this the same as 5Kc? */
343     case MIPS_5Kc: other_stuff = COP1_REVISION_DOUBLE
344     | COP1_REVISION_SINGLE;
345     case MIPS_R5000:
346     case MIPS_RM5200: fpu_rev = cpu->cd.mips.cpu_type.rev;
347     other_stuff |= 0x10;
348     /* or cpu->cd.mips.cpu_type.sub ? TODO */
349     break;
350     case MIPS_R10000: fpu_rev = MIPS_R10000; break;
351     case MIPS_R12000: fpu_rev = 0x9; break;
352     default: fpu_rev = MIPS_SOFT;
353     }
354    
355     c->fcr[COP1_REVISION] = (fpu_rev << 8) | other_stuff;
356    
357     #if 0
358     /* These are mentioned in the MIPS64 documentation: */
359     + (1 << 16) /* single */
360     + (1 << 17) /* double */
361     + (1 << 18) /* paired-single */
362     + (1 << 19) /* 3d */
363     #endif
364     }
365    
366    
367     /*
368     * mips_coproc_new():
369     *
370     * Create a new MIPS coprocessor object.
371     */
372     struct mips_coproc *mips_coproc_new(struct cpu *cpu, int coproc_nr)
373     {
374     struct mips_coproc *c;
375    
376     c = malloc(sizeof(struct mips_coproc));
377     if (c == NULL) {
378     fprintf(stderr, "out of memory\n");
379     exit(1);
380     }
381    
382     memset(c, 0, sizeof(struct mips_coproc));
383     c->coproc_nr = coproc_nr;
384    
385     if (coproc_nr == 0) {
386     c->nr_of_tlbs = cpu->cd.mips.cpu_type.nr_of_tlb_entries;
387     c->tlbs = malloc(c->nr_of_tlbs * sizeof(struct mips_tlb));
388     if (c->tlbs == NULL) {
389     fprintf(stderr, "mips_coproc_new(): out of memory\n");
390     exit(1);
391     }
392    
393     /*
394     * Start with nothing in the status register. This makes sure
395     * that we are running in kernel mode with all interrupts
396     * disabled.
397     */
398     c->reg[COP0_STATUS] = 0;
399    
400     /* For userland emulation, enable all four coprocessors: */
401     if (cpu->machine->userland_emul)
402     c->reg[COP0_STATUS] |=
403     ((uint32_t)0xf << STATUS_CU_SHIFT);
404    
405     /* Hm. Enable coprocessors 0 and 1 even if we're not just
406     emulating userland? TODO: Think about this. */
407     if (cpu->machine->prom_emulation)
408     c->reg[COP0_STATUS] |=
409     ((uint32_t)0x3 << STATUS_CU_SHIFT);
410    
411     if (!cpu->machine->prom_emulation)
412     c->reg[COP0_STATUS] |= STATUS_BEV;
413    
414     /* Note: .rev may contain the company ID as well! */
415     c->reg[COP0_PRID] =
416     (0x00 << 24) /* Company Options */
417     | (0x00 << 16) /* Company ID */
418     | (cpu->cd.mips.cpu_type.rev << 8) /* Processor ID */
419     | (cpu->cd.mips.cpu_type.sub) /* Revision */
420     ;
421    
422     c->reg[COP0_WIRED] = 0;
423    
424     initialize_cop0_config(cpu, c);
425    
426     /* Make sure the status register is sign-extended nicely: */
427     c->reg[COP0_STATUS] = (int64_t)(int32_t)c->reg[COP0_STATUS];
428     }
429    
430     if (coproc_nr == 1)
431     initialize_cop1(cpu, c);
432    
433     return c;
434     }
435    
436    
437     /*
438     * mips_coproc_tlb_set_entry():
439     *
440     * Used by machine setup code, if a specific machine emulation starts up
441     * with hardcoded virtual to physical mappings.
442     */
443     void mips_coproc_tlb_set_entry(struct cpu *cpu, int entrynr, int size,
444     uint64_t vaddr, uint64_t paddr0, uint64_t paddr1,
445     int valid0, int valid1, int dirty0, int dirty1, int global, int asid,
446     int cachealgo0, int cachealgo1)
447     {
448     if (entrynr < 0 || entrynr >= cpu->cd.mips.coproc[0]->nr_of_tlbs) {
449     printf("mips_coproc_tlb_set_entry(): invalid entry nr: %i\n",
450     entrynr);
451     exit(1);
452     }
453    
454     switch (cpu->cd.mips.cpu_type.mmu_model) {
455     case MMU3K:
456     if (size != 4096) {
457     printf("mips_coproc_tlb_set_entry(): invalid pagesize "
458     "(%i) for MMU3K\n", size);
459     exit(1);
460     }
461     cpu->cd.mips.coproc[0]->tlbs[entrynr].hi =
462     (vaddr & R2K3K_ENTRYHI_VPN_MASK) |
463     ((asid << R2K3K_ENTRYHI_ASID_SHIFT) &
464     R2K3K_ENTRYHI_ASID_MASK);
465     cpu->cd.mips.coproc[0]->tlbs[entrynr].lo0 =
466     (paddr0 & R2K3K_ENTRYLO_PFN_MASK) |
467     (cachealgo0? R2K3K_ENTRYLO_N : 0) |
468     (dirty0? R2K3K_ENTRYLO_D : 0) |
469     (valid0? R2K3K_ENTRYLO_V : 0) |
470     (global? R2K3K_ENTRYLO_G : 0);
471     break;
472     default:
473     /* MMU4K and MMU10K, etc: */
474     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
475     cpu->cd.mips.coproc[0]->tlbs[entrynr].hi =
476     (vaddr & ENTRYHI_VPN2_MASK_R10K) |
477     (vaddr & ENTRYHI_R_MASK) |
478     (asid & ENTRYHI_ASID) |
479     (global? TLB_G : 0);
480     else
481     cpu->cd.mips.coproc[0]->tlbs[entrynr].hi =
482     (vaddr & ENTRYHI_VPN2_MASK) |
483     (vaddr & ENTRYHI_R_MASK) |
484     (asid & ENTRYHI_ASID) |
485     (global? TLB_G : 0);
486     /* NOTE: The pagemask size is for a "dual" page: */
487     cpu->cd.mips.coproc[0]->tlbs[entrynr].mask =
488     (2*size - 1) & ~0x1fff;
489     cpu->cd.mips.coproc[0]->tlbs[entrynr].lo0 =
490     (((paddr0 >> 12) << ENTRYLO_PFN_SHIFT) &
491     ENTRYLO_PFN_MASK) |
492     (dirty0? ENTRYLO_D : 0) |
493     (valid0? ENTRYLO_V : 0) |
494     (global? ENTRYLO_G : 0) |
495     ((cachealgo0 << ENTRYLO_C_SHIFT) & ENTRYLO_C_MASK);
496     cpu->cd.mips.coproc[0]->tlbs[entrynr].lo1 =
497     (((paddr1 >> 12) << ENTRYLO_PFN_SHIFT) &
498     ENTRYLO_PFN_MASK) |
499     (dirty1? ENTRYLO_D : 0) |
500     (valid1? ENTRYLO_V : 0) |
501     (global? ENTRYLO_G : 0) |
502     ((cachealgo1 << ENTRYLO_C_SHIFT) & ENTRYLO_C_MASK);
503     /* TODO: R4100, 1KB pages etc */
504     }
505     }
506    
507    
508     /*
509     * old_update_translation_table():
510     */
511     static void old_update_translation_table(struct cpu *cpu, uint64_t vaddr_page,
512     unsigned char *host_page, int writeflag, uint64_t paddr_page)
513     {
514     #ifdef BINTRANS
515     int a, b;
516     struct vth32_table *tbl1;
517     void *p;
518     uint32_t p_paddr;
519    
520     /* This table stuff only works for 32-bit mode: */
521     if (vaddr_page & 0x80000000ULL) {
522     if ((vaddr_page >> 32) != 0xffffffffULL)
523     return;
524     } else {
525     if ((vaddr_page >> 32) != 0)
526     return;
527     }
528    
529     a = (vaddr_page >> 22) & 0x3ff;
530     b = (vaddr_page >> 12) & 0x3ff;
531     /* printf("vaddr = %08x, a = %03x, b = %03x\n",
532     (int)vaddr_page,a, b); */
533     tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a];
534     /* printf("tbl1 = %p\n", tbl1); */
535     if (tbl1 == cpu->cd.mips.vaddr_to_hostaddr_nulltable) {
536     /* Allocate a new table1: */
537     /* printf("ALLOCATING a new table1, 0x%08x - "
538     "0x%08x\n", a << 22, (a << 22) + 0x3fffff); */
539     if (cpu->cd.mips.next_free_vth_table == NULL) {
540     tbl1 = malloc(sizeof(struct vth32_table));
541     if (tbl1 == NULL) {
542     fprintf(stderr, "out of mem\n");
543     exit(1);
544     }
545     memset(tbl1, 0, sizeof(struct vth32_table));
546     } else {
547     tbl1 = cpu->cd.mips.next_free_vth_table;
548     cpu->cd.mips.next_free_vth_table =
549     tbl1->next_free;
550     tbl1->next_free = NULL;
551     }
552     cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a] = tbl1;
553     if (tbl1->refcount != 0) {
554     printf("INTERNAL ERROR in coproc.c\n");
555     exit(1);
556     }
557     }
558     p = tbl1->haddr_entry[b];
559     p_paddr = tbl1->paddr_entry[b];
560     /* printf(" p = %p\n", p); */
561     if (p == NULL && p_paddr == 0 &&
562     (host_page!=NULL || paddr_page!=0)) {
563     tbl1->refcount ++;
564     /* printf("ADDING %08x -> %p wf=%i (refcount is "
565     "now %i)\n", (int)vaddr_page, host_page,
566     writeflag, tbl1->refcount); */
567     }
568     if (writeflag == -1) {
569     /* Forced downgrade to read-only: */
570     tbl1->haddr_entry[b] = (void *)
571     ((size_t)tbl1->haddr_entry[b] & ~1);
572     } else if (writeflag==0 && (size_t)p&1 && host_page != NULL) {
573     /* Don't degrade a page from writable to readonly. */
574     } else {
575     if (host_page != NULL)
576     tbl1->haddr_entry[b] = (void *)
577     ((size_t)host_page + (writeflag?1:0));
578     else
579     tbl1->haddr_entry[b] = NULL;
580     tbl1->paddr_entry[b] = paddr_page;
581     }
582     tbl1->bintrans_chunks[b] = NULL;
583     #endif
584     }
585    
586    
587     /*
588     * update_translation_table():
589     */
590     void update_translation_table(struct cpu *cpu, uint64_t vaddr_page,
591     unsigned char *host_page, int writeflag, uint64_t paddr_page)
592     {
593     #ifdef BINTRANS
594     if (!cpu->machine->bintrans_enable)
595     return;
596    
597     if (writeflag > 0)
598     bintrans_invalidate(cpu, paddr_page);
599    
600     if (cpu->machine->old_bintrans_enable) {
601     old_update_translation_table(cpu, vaddr_page, host_page,
602     writeflag, paddr_page);
603     return;
604     }
605    
606     /* TODO */
607     /* printf("update_translation_table(): TODO\n"); */
608     #endif
609     }
610    
611    
612     #ifdef BINTRANS
613     /*
614     * invalidate_table_entry():
615     */
616     static void invalidate_table_entry(struct cpu *cpu, uint64_t vaddr)
617     {
618     int a, b;
619     struct vth32_table *tbl1;
620     void *p;
621     uint32_t p_paddr;
622    
623     if (!cpu->machine->old_bintrans_enable) {
624     /* printf("invalidate_table_entry(): New: TODO\n"); */
625     return;
626     }
627    
628     /* This table stuff only works for 32-bit mode: */
629     if (vaddr & 0x80000000ULL) {
630     if ((vaddr >> 32) != 0xffffffffULL) {
631     fatal("invalidate_table_entry(): vaddr = 0x%016llx\n",
632     (long long)vaddr);
633     return;
634     }
635     } else {
636     if ((vaddr >> 32) != 0) {
637     fatal("invalidate_table_entry(): vaddr = 0x%016llx\n",
638     (long long)vaddr);
639     return;
640     }
641     }
642    
643     a = (vaddr >> 22) & 0x3ff;
644     b = (vaddr >> 12) & 0x3ff;
645    
646     /* printf("vaddr = %08x, a = %03x, b = %03x\n", (int)vaddr,a, b); */
647    
648     tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a];
649     /* printf("tbl1 = %p\n", tbl1); */
650     p = tbl1->haddr_entry[b];
651     p_paddr = tbl1->paddr_entry[b];
652     tbl1->bintrans_chunks[b] = NULL;
653     /* printf(" p = %p\n", p); */
654     if (p != NULL || p_paddr != 0) {
655     /* printf("Found a mapping, "
656     "vaddr = %08x, a = %03x, b = %03x\n", (int)vaddr,a, b); */
657     tbl1->haddr_entry[b] = NULL;
658     tbl1->paddr_entry[b] = 0;
659     tbl1->refcount --;
660     if (tbl1->refcount == 0) {
661     cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a] =
662     cpu->cd.mips.vaddr_to_hostaddr_nulltable;
663     /* "free" tbl1: */
664     tbl1->next_free = cpu->cd.mips.next_free_vth_table;
665     cpu->cd.mips.next_free_vth_table = tbl1;
666     }
667     }
668     }
669    
670    
671     /*
672     * clear_all_chunks_from_all_tables():
673     */
674     void clear_all_chunks_from_all_tables(struct cpu *cpu)
675     {
676     int a, b;
677     struct vth32_table *tbl1;
678    
679     if (!cpu->machine->old_bintrans_enable) {
680     printf("clear_all_chunks_from_all_tables(): New: TODO\n");
681     return;
682     }
683    
684     for (a=0; a<0x400; a++) {
685     tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a];
686     if (tbl1 != cpu->cd.mips.vaddr_to_hostaddr_nulltable) {
687     for (b=0; b<0x400; b++)
688     tbl1->bintrans_chunks[b] = NULL;
689     }
690     }
691     }
692     #endif
693    
694    
695     /*
696     * mips_invalidate_translation_caches_paddr():
697     *
698     * Invalidate based on physical address.
699     */
700     void mips_invalidate_translation_caches_paddr(struct cpu *cpu, uint64_t paddr)
701     {
702     #ifdef BINTRANS
703     paddr &= ~0xfff;
704    
705     if (cpu->machine->bintrans_enable) {
706     #if 1
707     int i;
708     uint64_t tlb_paddr0, tlb_paddr1;
709     uint64_t tlb_vaddr;
710     uint64_t p, p2;
711    
712     switch (cpu->cd.mips.cpu_type.mmu_model) {
713     case MMU3K:
714     for (i=0; i<64; i++) {
715     tlb_paddr0 = cpu->cd.mips.coproc[0]->
716     tlbs[i].lo0 & R2K3K_ENTRYLO_PFN_MASK;
717     tlb_vaddr = cpu->cd.mips.coproc[0]->
718     tlbs[i].hi & R2K3K_ENTRYHI_VPN_MASK;
719     tlb_vaddr = (int64_t)(int32_t)tlb_vaddr;
720     if ((cpu->cd.mips.coproc[0]->tlbs[i].lo0 &
721     R2K3K_ENTRYLO_V) && tlb_paddr0 == paddr)
722     invalidate_table_entry(cpu, tlb_vaddr);
723     }
724     break;
725     default:
726     for (i=0; i<cpu->cd.mips.coproc[0]->nr_of_tlbs; i++) {
727     int psize = 12;
728     int or_pmask = 0x1fff;
729     int phys_shift = 12;
730    
731     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
732     or_pmask = 0x7ff;
733     phys_shift = 10;
734     }
735     switch (cpu->cd.mips.coproc[0]->
736     tlbs[i].mask | or_pmask) {
737     case 0x000007ff: psize = 10; break;
738     case 0x00001fff: psize = 12; break;
739     case 0x00007fff: psize = 14; break;
740     case 0x0001ffff: psize = 16; break;
741     case 0x0007ffff: psize = 18; break;
742     case 0x001fffff: psize = 20; break;
743     case 0x007fffff: psize = 22; break;
744     case 0x01ffffff: psize = 24; break;
745     case 0x07ffffff: psize = 26; break;
746     default:
747     printf("invalidate_translation_caches"
748     "_paddr(): bad pagemask?\n");
749     }
750     tlb_paddr0 = (cpu->cd.mips.coproc[0]->tlbs[i].
751     lo0 & ENTRYLO_PFN_MASK)>>ENTRYLO_PFN_SHIFT;
752     tlb_paddr1 = (cpu->cd.mips.coproc[0]->tlbs[i].
753     lo1 & ENTRYLO_PFN_MASK)>>ENTRYLO_PFN_SHIFT;
754     tlb_paddr0 <<= phys_shift;
755     tlb_paddr1 <<= phys_shift;
756     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
757     tlb_vaddr = cpu->cd.mips.coproc[0]->
758     tlbs[i].hi & ENTRYHI_VPN2_MASK_R10K;
759     if (tlb_vaddr & ((int64_t)1 << 43))
760     tlb_vaddr |=
761     0xfffff00000000000ULL;
762     } else {
763     tlb_vaddr = cpu->cd.mips.coproc[0]->
764     tlbs[i].hi & ENTRYHI_VPN2_MASK;
765     if (tlb_vaddr & ((int64_t)1 << 39))
766     tlb_vaddr |=
767     0xffffff0000000000ULL;
768     }
769     if ((cpu->cd.mips.coproc[0]->tlbs[i].lo0 &
770     ENTRYLO_V) && paddr >= tlb_paddr0 &&
771     paddr < tlb_paddr0 + (1<<psize)) {
772     p2 = 1 << psize;
773     for (p=0; p<p2; p+=4096)
774     invalidate_table_entry(cpu,
775     tlb_vaddr + p);
776     }
777     if ((cpu->cd.mips.coproc[0]->tlbs[i].lo1 &
778     ENTRYLO_V) && paddr >= tlb_paddr1 &&
779     paddr < tlb_paddr1 + (1<<psize)) {
780     p2 = 1 << psize;
781     for (p=0; p<p2; p+=4096)
782     invalidate_table_entry(cpu,
783     tlb_vaddr + p +
784     (1 << psize));
785     }
786     }
787     }
788     #endif
789    
790     if (paddr < 0x20000000) {
791     invalidate_table_entry(cpu, 0xffffffff80000000ULL
792     + paddr);
793     invalidate_table_entry(cpu, 0xffffffffa0000000ULL
794     + paddr);
795     }
796     }
797    
798     #if 0
799     {
800     int i;
801    
802     /* TODO: Don't invalidate everything. */
803     for (i=0; i<N_BINTRANS_VADDR_TO_HOST; i++)
804     cpu->bintrans_data_hostpage[i] = NULL;
805     }
806     #endif
807    
808     #endif
809     }
810    
811    
812     /*
813     * invalidate_translation_caches():
814     *
815     * This is necessary for every change to the TLB, and when the ASID is changed,
816     * so that for example user-space addresses are not cached when they should
817     * not be.
818     */
819     static void invalidate_translation_caches(struct cpu *cpu,
820     int all, uint64_t vaddr, int kernelspace, int old_asid_to_invalidate)
821     {
822     int i;
823    
824     /* printf("inval(all=%i, kernel=%i, addr=%016llx)\n",
825     all, kernelspace, (long long)vaddr); */
826    
827     #ifdef BINTRANS
828     if (!cpu->machine->bintrans_enable)
829     goto nobintrans;
830    
831     if (all) {
832     int i;
833     uint64_t tlb_vaddr;
834     switch (cpu->cd.mips.cpu_type.mmu_model) {
835     case MMU3K:
836     for (i=0; i<64; i++) {
837     tlb_vaddr = cpu->cd.mips.coproc[0]->tlbs[i].hi
838     & R2K3K_ENTRYHI_VPN_MASK;
839     tlb_vaddr = (int64_t)(int32_t)tlb_vaddr;
840     if ((cpu->cd.mips.coproc[0]->tlbs[i].lo0 &
841     R2K3K_ENTRYLO_V) && (tlb_vaddr &
842     0xc0000000ULL) != 0x80000000ULL) {
843     int asid = (cpu->cd.mips.coproc[0]->
844     tlbs[i].hi & R2K3K_ENTRYHI_ASID_MASK
845     ) >> R2K3K_ENTRYHI_ASID_SHIFT;
846     if (old_asid_to_invalidate < 0 ||
847     old_asid_to_invalidate == asid)
848     invalidate_table_entry(cpu,
849     tlb_vaddr);
850     }
851     }
852     break;
853     default:
854     for (i=0; i<cpu->cd.mips.coproc[0]->nr_of_tlbs; i++) {
855     int psize = 10, or_pmask = 0x1fff;
856     int phys_shift = 12;
857    
858     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
859     or_pmask = 0x7ff;
860     phys_shift = 10;
861     }
862    
863     switch (cpu->cd.mips.coproc[0]->tlbs[i].mask
864     | or_pmask) {
865     case 0x000007ff: psize = 10; break;
866     case 0x00001fff: psize = 12; break;
867     case 0x00007fff: psize = 14; break;
868     case 0x0001ffff: psize = 16; break;
869     case 0x0007ffff: psize = 18; break;
870     case 0x001fffff: psize = 20; break;
871     case 0x007fffff: psize = 22; break;
872     case 0x01ffffff: psize = 24; break;
873     case 0x07ffffff: psize = 26; break;
874     default:
875     printf("invalidate_translation_caches"
876     "(): bad pagemask?\n");
877     }
878    
879     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
880     tlb_vaddr = cpu->cd.mips.coproc[0]->
881     tlbs[i].hi & ENTRYHI_VPN2_MASK_R10K;
882     if (tlb_vaddr & ((int64_t)1 << 43))
883     tlb_vaddr |=
884     0xfffff00000000000ULL;
885     } else {
886     tlb_vaddr = cpu->cd.mips.coproc[0]->
887     tlbs[i].hi & ENTRYHI_VPN2_MASK;
888     if (tlb_vaddr & ((int64_t)1 << 39))
889     tlb_vaddr |=
890     0xffffff0000000000ULL;
891     }
892    
893     /* TODO: Check the ASID etc. */
894    
895     invalidate_table_entry(cpu, tlb_vaddr);
896     invalidate_table_entry(cpu, tlb_vaddr |
897     (1 << psize));
898     }
899     }
900     } else
901     invalidate_table_entry(cpu, vaddr);
902    
903     nobintrans:
904    
905     /* TODO: Don't invalidate everything. */
906     for (i=0; i<N_BINTRANS_VADDR_TO_HOST; i++)
907     cpu->cd.mips.bintrans_data_hostpage[i] = NULL;
908     #endif
909    
910     if (kernelspace)
911     all = 1;
912    
913     #ifdef USE_TINY_CACHE
914     {
915     vaddr >>= 12;
916    
917     /* Invalidate the tiny translation cache... */
918     if (!cpu->machine->bintrans_enable)
919     for (i=0; i<N_TRANSLATION_CACHE_INSTR; i++)
920     if (all || vaddr == (cpu->cd.mips.
921     translation_cache_instr[i].vaddr_pfn))
922     cpu->cd.mips.translation_cache_instr[i].wf = 0;
923    
924     if (!cpu->machine->bintrans_enable)
925     for (i=0; i<N_TRANSLATION_CACHE_DATA; i++)
926     if (all || vaddr == (cpu->cd.mips.
927     translation_cache_data[i].vaddr_pfn))
928     cpu->cd.mips.translation_cache_data[i].wf = 0;
929     }
930     #endif
931     }
932    
933    
934     /*
935     * coproc_register_read();
936     *
937     * Read a value from a MIPS coprocessor register.
938     */
939     void coproc_register_read(struct cpu *cpu,
940     struct mips_coproc *cp, int reg_nr, uint64_t *ptr)
941     {
942     int unimpl = 1;
943    
944     if (cp->coproc_nr==0 && reg_nr==COP0_INDEX) unimpl = 0;
945     if (cp->coproc_nr==0 && reg_nr==COP0_RANDOM) unimpl = 0;
946     if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYLO0) unimpl = 0;
947     if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYLO1) unimpl = 0;
948     if (cp->coproc_nr==0 && reg_nr==COP0_CONTEXT) unimpl = 0;
949     if (cp->coproc_nr==0 && reg_nr==COP0_PAGEMASK) unimpl = 0;
950     if (cp->coproc_nr==0 && reg_nr==COP0_WIRED) unimpl = 0;
951     if (cp->coproc_nr==0 && reg_nr==COP0_BADVADDR) unimpl = 0;
952     if (cp->coproc_nr==0 && reg_nr==COP0_COUNT) unimpl = 0;
953     if (cp->coproc_nr==0 && reg_nr==COP0_ENTRYHI) unimpl = 0;
954     if (cp->coproc_nr==0 && reg_nr==COP0_COMPARE) unimpl = 0;
955     if (cp->coproc_nr==0 && reg_nr==COP0_STATUS) unimpl = 0;
956     if (cp->coproc_nr==0 && reg_nr==COP0_CAUSE) unimpl = 0;
957     if (cp->coproc_nr==0 && reg_nr==COP0_EPC) unimpl = 0;
958     if (cp->coproc_nr==0 && reg_nr==COP0_PRID) unimpl = 0;
959     if (cp->coproc_nr==0 && reg_nr==COP0_CONFIG) unimpl = 0;
960     if (cp->coproc_nr==0 && reg_nr==COP0_LLADDR) unimpl = 0;
961     if (cp->coproc_nr==0 && reg_nr==COP0_WATCHLO) unimpl = 0;
962     if (cp->coproc_nr==0 && reg_nr==COP0_WATCHHI) unimpl = 0;
963     if (cp->coproc_nr==0 && reg_nr==COP0_XCONTEXT) unimpl = 0;
964     if (cp->coproc_nr==0 && reg_nr==COP0_ERRCTL) unimpl = 0;
965     if (cp->coproc_nr==0 && reg_nr==COP0_CACHEERR) unimpl = 0;
966     if (cp->coproc_nr==0 && reg_nr==COP0_TAGDATA_LO) unimpl = 0;
967     if (cp->coproc_nr==0 && reg_nr==COP0_TAGDATA_HI) unimpl = 0;
968     if (cp->coproc_nr==0 && reg_nr==COP0_ERROREPC) unimpl = 0;
969     if (cp->coproc_nr==0 && reg_nr==COP0_RESERV22) {
970     /* Used by Linux on Linksys WRT54G */
971     unimpl = 0;
972     }
973     if (cp->coproc_nr==0 && reg_nr==COP0_DEBUG) unimpl = 0;
974     if (cp->coproc_nr==0 && reg_nr==COP0_PERFCNT) unimpl = 0;
975     if (cp->coproc_nr==0 && reg_nr==COP0_DESAVE) unimpl = 0;
976    
977     if (cp->coproc_nr==1) unimpl = 0;
978    
979     if (unimpl) {
980     fatal("cpu%i: warning: read from unimplemented coproc%i"
981     " register %i (%s)\n", cpu->cpu_id, cp->coproc_nr, reg_nr,
982     cp->coproc_nr==0? cop0_names[reg_nr] : "?");
983    
984     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0,
985     cp->coproc_nr, 0, 0, 0);
986     return;
987     }
988    
989     *ptr = cp->reg[reg_nr];
990     }
991    
992    
993     /*
994     * coproc_register_write();
995     *
996     * Write a value to a MIPS coprocessor register.
997     */
998     void coproc_register_write(struct cpu *cpu,
999     struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int flag64)
1000     {
1001     int unimpl = 1;
1002     int readonly = 0;
1003     uint64_t tmp = *ptr;
1004     uint64_t tmp2 = 0, old;
1005     int inval = 0, old_asid, oldmode;
1006    
1007     switch (cp->coproc_nr) {
1008     case 0:
1009     /* COPROC 0: */
1010     switch (reg_nr) {
1011     case COP0_INDEX:
1012     case COP0_RANDOM:
1013     unimpl = 0;
1014     break;
1015     case COP0_ENTRYLO0:
1016     unimpl = 0;
1017     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
1018     (tmp & 0xff)!=0) {
1019     /* char *symbol;
1020     uint64_t offset;
1021     symbol = get_symbol_name(
1022     cpu->cd.mips.pc_last, &offset);
1023     fatal("YO! pc = 0x%08llx <%s> "
1024     "lo=%016llx\n", (long long)
1025     cpu->cd.mips.pc_last, symbol? symbol :
1026     "no symbol", (long long)tmp); */
1027     tmp &= (R2K3K_ENTRYLO_PFN_MASK |
1028     R2K3K_ENTRYLO_N | R2K3K_ENTRYLO_D |
1029     R2K3K_ENTRYLO_V | R2K3K_ENTRYLO_G);
1030     } else if (cpu->cd.mips.cpu_type.mmu_model == MMU4K) {
1031     tmp &= (ENTRYLO_PFN_MASK | ENTRYLO_C_MASK |
1032     ENTRYLO_D | ENTRYLO_V | ENTRYLO_G);
1033     }
1034     break;
1035     case COP0_BADVADDR:
1036     /* Hm. Irix writes to this register. (Why?) */
1037     unimpl = 0;
1038     break;
1039     case COP0_ENTRYLO1:
1040     unimpl = 0;
1041     if (cpu->cd.mips.cpu_type.mmu_model == MMU4K) {
1042     tmp &= (ENTRYLO_PFN_MASK | ENTRYLO_C_MASK |
1043     ENTRYLO_D | ENTRYLO_V | ENTRYLO_G);
1044     }
1045     break;
1046     case COP0_CONTEXT:
1047     old = cp->reg[COP0_CONTEXT];
1048     cp->reg[COP0_CONTEXT] = tmp;
1049     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1050     cp->reg[COP0_CONTEXT] &=
1051     ~R2K3K_CONTEXT_BADVPN_MASK;
1052     cp->reg[COP0_CONTEXT] |=
1053     (old & R2K3K_CONTEXT_BADVPN_MASK);
1054     } else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1055     cp->reg[COP0_CONTEXT] &=
1056     ~CONTEXT_BADVPN2_MASK_R4100;
1057     cp->reg[COP0_CONTEXT] |=
1058     (old & CONTEXT_BADVPN2_MASK_R4100);
1059     } else {
1060     cp->reg[COP0_CONTEXT] &=
1061     ~CONTEXT_BADVPN2_MASK;
1062     cp->reg[COP0_CONTEXT] |=
1063     (old & CONTEXT_BADVPN2_MASK);
1064     }
1065     return;
1066     case COP0_PAGEMASK:
1067     tmp2 = tmp >> PAGEMASK_SHIFT;
1068     if (tmp2 != 0x000 &&
1069     tmp2 != 0x003 &&
1070     tmp2 != 0x00f &&
1071     tmp2 != 0x03f &&
1072     tmp2 != 0x0ff &&
1073     tmp2 != 0x3ff &&
1074     tmp2 != 0xfff)
1075     fatal("cpu%i: trying to write an invalid"
1076     " pagemask 0x%08lx to COP0_PAGEMASK\n",
1077     cpu->cpu_id, (long)tmp);
1078     unimpl = 0;
1079     break;
1080     case COP0_WIRED:
1081     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1082     fatal("cpu%i: r2k/r3k wired register must "
1083     "always be 8\n", cpu->cpu_id);
1084     tmp = 8;
1085     }
1086     cp->reg[COP0_RANDOM] = cp->nr_of_tlbs-1;
1087     tmp &= INDEX_MASK;
1088     unimpl = 0;
1089     break;
1090     case COP0_COUNT:
1091     if (tmp != (int64_t)(int32_t)tmp)
1092     fatal("WARNING: trying to write a 64-bit value"
1093     " to the COUNT register!\n");
1094     tmp = (int64_t)(int32_t)tmp;
1095     unimpl = 0;
1096     break;
1097     case COP0_COMPARE:
1098     /* Clear the timer interrupt bit (bit 7): */
1099     cpu->cd.mips.compare_register_set = 1;
1100     mips_cpu_interrupt_ack(cpu, 7);
1101     if (tmp != (int64_t)(int32_t)tmp)
1102     fatal("WARNING: trying to write a 64-bit value"
1103     " to the COMPARE register!\n");
1104     tmp = (int64_t)(int32_t)tmp;
1105     unimpl = 0;
1106     break;
1107     case COP0_ENTRYHI:
1108     /*
1109     * Translation caches must be invalidated, because the
1110     * address space might change (if the ASID changes).
1111     */
1112     switch (cpu->cd.mips.cpu_type.mmu_model) {
1113     case MMU3K:
1114     old_asid = (cp->reg[COP0_ENTRYHI] &
1115     R2K3K_ENTRYHI_ASID_MASK) >>
1116     R2K3K_ENTRYHI_ASID_SHIFT;
1117     if ((cp->reg[COP0_ENTRYHI] &
1118     R2K3K_ENTRYHI_ASID_MASK) !=
1119     (tmp & R2K3K_ENTRYHI_ASID_MASK))
1120     inval = 1;
1121     break;
1122     default:
1123     old_asid = cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID;
1124     if ((cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID) !=
1125     (tmp & ENTRYHI_ASID))
1126     inval = 1;
1127     break;
1128     }
1129     if (inval)
1130     invalidate_translation_caches(cpu, 1, 0, 0,
1131     old_asid);
1132     unimpl = 0;
1133     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K &&
1134     (tmp & 0x3f)!=0) {
1135     /* char *symbol;
1136     uint64_t offset;
1137     symbol = get_symbol_name(cpu->
1138     cd.mips.pc_last, &offset);
1139     fatal("YO! pc = 0x%08llx <%s> "
1140     "hi=%016llx\n", (long long)cpu->
1141     cd.mips.pc_last, symbol? symbol :
1142     "no symbol", (long long)tmp); */
1143     tmp &= ~0x3f;
1144     }
1145     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
1146     tmp &= (R2K3K_ENTRYHI_VPN_MASK |
1147     R2K3K_ENTRYHI_ASID_MASK);
1148     else if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
1149     tmp &= (ENTRYHI_R_MASK |
1150     ENTRYHI_VPN2_MASK_R10K | ENTRYHI_ASID);
1151     else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
1152     tmp &= (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK |
1153     0x1800 | ENTRYHI_ASID);
1154     else
1155     tmp &= (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK |
1156     ENTRYHI_ASID);
1157     break;
1158     case COP0_EPC:
1159     unimpl = 0;
1160     break;
1161     case COP0_PRID:
1162     readonly = 1;
1163     break;
1164     case COP0_CONFIG:
1165     /* fatal("COP0_CONFIG: modifying K0 bits: "
1166     "0x%08x => ", cp->reg[reg_nr]); */
1167     tmp = *ptr;
1168     tmp &= 0x3; /* only bits 2..0 can be written */
1169     cp->reg[reg_nr] &= ~(0x3); cp->reg[reg_nr] |= tmp;
1170     /* fatal("0x%08x\n", cp->reg[reg_nr]); */
1171     return;
1172     case COP0_STATUS:
1173     oldmode = cp->reg[COP0_STATUS];
1174     tmp &= ~(1 << 21); /* bit 21 is read-only */
1175     /* Changing from kernel to user mode? Then
1176     invalidate some translation caches: */
1177     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
1178     if (!(oldmode & MIPS1_SR_KU_CUR)
1179     && (tmp & MIPS1_SR_KU_CUR))
1180     invalidate_translation_caches(cpu,
1181     0, 0, 1, 0);
1182     } else {
1183     /* TODO: don't hardcode */
1184     if ((oldmode & 0xff) != (tmp & 0xff))
1185     invalidate_translation_caches(
1186     cpu, 0, 0, 1, 0);
1187     }
1188     unimpl = 0;
1189     break;
1190     case COP0_CAUSE:
1191     /* A write to the cause register only
1192     affects IM bits 0 and 1: */
1193     cp->reg[reg_nr] &= ~(0x3 << STATUS_IM_SHIFT);
1194     cp->reg[reg_nr] |= (tmp & (0x3 << STATUS_IM_SHIFT));
1195     if (!(cp->reg[COP0_CAUSE] & STATUS_IM_MASK))
1196     cpu->cd.mips.cached_interrupt_is_possible = 0;
1197     else
1198     cpu->cd.mips.cached_interrupt_is_possible = 1;
1199     return;
1200     case COP0_FRAMEMASK:
1201     /* TODO: R10000 */
1202     unimpl = 0;
1203     break;
1204     case COP0_TAGDATA_LO:
1205     case COP0_TAGDATA_HI:
1206     /* TODO: R4300 and others? */
1207     unimpl = 0;
1208     break;
1209     case COP0_LLADDR:
1210     unimpl = 0;
1211     break;
1212     case COP0_WATCHLO:
1213     case COP0_WATCHHI:
1214     unimpl = 0;
1215     break;
1216     case COP0_XCONTEXT:
1217     /*
1218     * TODO: According to the R10000 manual, the R4400
1219     * shares the PTEbase portion of the context registers
1220     * (that is, xcontext and context). On R10000, they
1221     * are separate registers.
1222     */
1223     /* debug("[ xcontext 0x%016llx ]\n", tmp); */
1224     unimpl = 0;
1225     break;
1226    
1227     /* Most of these are actually TODOs: */
1228     case COP0_ERROREPC:
1229     case COP0_DEPC:
1230     case COP0_RESERV22: /* Used by Linux on Linksys WRT54G */
1231     case COP0_DESAVE:
1232     case COP0_PERFCNT:
1233     case COP0_ERRCTL: /* R10000 */
1234     unimpl = 0;
1235     break;
1236     }
1237     break;
1238    
1239     case 1:
1240     /* COPROC 1: */
1241     unimpl = 0;
1242     break;
1243     }
1244    
1245     if (unimpl) {
1246     fatal("cpu%i: warning: write to unimplemented coproc%i "
1247     "register %i (%s), data = 0x%016llx\n", cpu->cpu_id,
1248     cp->coproc_nr, reg_nr, cp->coproc_nr==0?
1249     cop0_names[reg_nr] : "?", (long long)tmp);
1250    
1251     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0,
1252     cp->coproc_nr, 0, 0, 0);
1253     return;
1254     }
1255    
1256     if (readonly) {
1257     fatal("cpu%i: warning: write to READONLY coproc%i register "
1258     "%i ignored\n", cpu->cpu_id, cp->coproc_nr, reg_nr);
1259     return;
1260     }
1261    
1262     cp->reg[reg_nr] = tmp;
1263    
1264     if (!flag64)
1265     cp->reg[reg_nr] = (int64_t)(int32_t)cp->reg[reg_nr];
1266     }
1267    
1268    
1269     /*
1270     * MIPS floating-point stuff:
1271     *
1272     * TODO: Move this to some other file?
1273     */
1274     #define FMT_S 16
1275     #define FMT_D 17
1276     #define FMT_W 20
1277     #define FMT_L 21
1278     #define FMT_PS 22
1279    
1280     #define FPU_OP_ADD 1
1281     #define FPU_OP_SUB 2
1282     #define FPU_OP_MUL 3
1283     #define FPU_OP_DIV 4
1284     #define FPU_OP_SQRT 5
1285     #define FPU_OP_MOV 6
1286     #define FPU_OP_CVT 7
1287     #define FPU_OP_C 8
1288     #define FPU_OP_ABS 9
1289     #define FPU_OP_NEG 10
1290     /* TODO: CEIL.L, CEIL.W, FLOOR.L, FLOOR.W, RECIP, ROUND.L, ROUND.W,
1291     RSQRT */
1292    
1293    
1294     struct internal_float_value {
1295     double f;
1296     int nan;
1297     };
1298    
1299    
1300     /*
1301     * fpu_interpret_float_value():
1302     *
1303     * Interprets a float value from binary IEEE format into an
1304     * internal_float_value struct.
1305     */
1306     static void fpu_interpret_float_value(uint64_t reg,
1307     struct internal_float_value *fvp, int fmt)
1308     {
1309     int n_frac = 0, n_exp = 0;
1310     int i, nan, sign = 0, exponent;
1311     double fraction;
1312    
1313     memset(fvp, 0, sizeof(struct internal_float_value));
1314    
1315     /* n_frac and n_exp: */
1316     switch (fmt) {
1317     case FMT_S: n_frac = 23; n_exp = 8; break;
1318     case FMT_W: n_frac = 31; n_exp = 0; break;
1319     case FMT_D: n_frac = 52; n_exp = 11; break;
1320     case FMT_L: n_frac = 63; n_exp = 0; break;
1321     default:
1322     fatal("fpu_interpret_float_value(): "
1323     "unimplemented format %i\n", fmt);
1324     }
1325    
1326     /* exponent: */
1327     exponent = 0;
1328     switch (fmt) {
1329     case FMT_W:
1330     reg &= 0xffffffffULL;
1331     case FMT_L:
1332     break;
1333     case FMT_S:
1334     reg &= 0xffffffffULL;
1335     case FMT_D:
1336     exponent = (reg >> n_frac) & ((1 << n_exp) - 1);
1337     exponent -= (1 << (n_exp-1)) - 1;
1338     break;
1339     default:
1340     fatal("fpu_interpret_float_value(): unimplemented "
1341     "format %i\n", fmt);
1342     }
1343    
1344     /* nan: */
1345     nan = 0;
1346     switch (fmt) {
1347     case FMT_S:
1348     if (reg == 0x7fffffffULL || reg == 0x7fbfffffULL)
1349     nan = 1;
1350     break;
1351     case FMT_D:
1352     if (reg == 0x7fffffffffffffffULL ||
1353     reg == 0x7ff7ffffffffffffULL)
1354     nan = 1;
1355     break;
1356     }
1357    
1358     if (nan) {
1359     fvp->f = 1.0;
1360     goto no_reasonable_result;
1361     }
1362    
1363     /* fraction: */
1364     fraction = 0.0;
1365     switch (fmt) {
1366     case FMT_W:
1367     {
1368     int32_t r_int = reg;
1369     fraction = r_int;
1370     }
1371     break;
1372     case FMT_L:
1373     {
1374     int64_t r_int = reg;
1375     fraction = r_int;
1376     }
1377     break;
1378     case FMT_S:
1379     case FMT_D:
1380     /* sign: */
1381     sign = (reg >> 31) & 1;
1382     if (fmt == FMT_D)
1383     sign = (reg >> 63) & 1;
1384    
1385     fraction = 0.0;
1386     for (i=0; i<n_frac; i++) {
1387     int bit = (reg >> i) & 1;
1388     fraction /= 2.0;
1389     if (bit)
1390     fraction += 1.0;
1391     }
1392     /* Add implicit bit 0: */
1393     fraction = (fraction / 2.0) + 1.0;
1394     break;
1395     default:
1396     fatal("fpu_interpret_float_value(): "
1397     "unimplemented format %i\n", fmt);
1398     }
1399    
1400     /* form the value: */
1401     fvp->f = fraction;
1402    
1403     /* fatal("load reg=%016llx sign=%i exponent=%i fraction=%f ",
1404     (long long)reg, sign, exponent, fraction); */
1405    
1406     /* TODO: this is awful for exponents of large magnitude. */
1407     if (exponent > 0) {
1408     /*
1409     * NOTE / TODO:
1410     *
1411     * This is an ulgy workaround on Alpha, where it seems that
1412     * multiplying by 2, 1024 times causes a floating point
1413     * exception. (Triggered by running for example NetBSD/pmax
1414     * 2.0 on an Alpha.)
1415     */
1416     if (exponent == 1024)
1417     exponent = 1023;
1418    
1419     while (exponent-- > 0)
1420     fvp->f *= 2.0;
1421     } else if (exponent < 0) {
1422     while (exponent++ < 0)
1423     fvp->f /= 2.0;
1424     }
1425    
1426     if (sign)
1427     fvp->f = -fvp->f;
1428    
1429     no_reasonable_result:
1430     fvp->nan = nan;
1431    
1432     /* fatal("f = %f\n", fvp->f); */
1433     }
1434    
1435    
1436     /*
1437     * fpu_store_float_value():
1438     *
1439     * Stores a float value (actually a double) in fmt format.
1440     */
1441     static void fpu_store_float_value(struct mips_coproc *cp, int fd,
1442     double nf, int fmt, int nan)
1443     {
1444     int n_frac = 0, n_exp = 0, signofs=0;
1445     int i, exponent;
1446     uint64_t r = 0, r2;
1447     int64_t r3;
1448    
1449     /* n_frac and n_exp: */
1450     switch (fmt) {
1451     case FMT_S: n_frac = 23; n_exp = 8; signofs = 31; break;
1452     case FMT_W: n_frac = 31; n_exp = 0; signofs = 31; break;
1453     case FMT_D: n_frac = 52; n_exp = 11; signofs = 63; break;
1454     case FMT_L: n_frac = 63; n_exp = 0; signofs = 63; break;
1455     default:
1456     fatal("fpu_store_float_value(): unimplemented format"
1457     " %i\n", fmt);
1458     }
1459    
1460     if ((fmt == FMT_S || fmt == FMT_D) && nan)
1461     goto store_nan;
1462    
1463     /* fraction: */
1464     switch (fmt) {
1465     case FMT_W:
1466     case FMT_L:
1467     /*
1468     * This causes an implicit conversion of double to integer.
1469     * If nf < 0.0, then r2 will begin with a sequence of binary
1470     * 1's, which is ok.
1471     */
1472     r3 = nf;
1473     r2 = r3;
1474     r |= r2;
1475    
1476     if (fmt == FMT_W)
1477     r &= 0xffffffffULL;
1478     break;
1479     case FMT_S:
1480     case FMT_D:
1481     /* fatal("store f=%f ", nf); */
1482    
1483     /* sign bit: */
1484     if (nf < 0.0) {
1485     r |= ((uint64_t)1 << signofs);
1486     nf = -nf;
1487     }
1488    
1489     /*
1490     * How to convert back from double to exponent + fraction:
1491     * We want fraction to be 1.xxx, that is
1492     * 1.0 <= fraction < 2.0
1493     *
1494     * This method is very slow but should work:
1495     */
1496     exponent = 0;
1497     while (nf < 1.0 && exponent > -1023) {
1498     nf *= 2.0;
1499     exponent --;
1500     }
1501     while (nf >= 2.0 && exponent < 1023) {
1502     nf /= 2.0;
1503     exponent ++;
1504     }
1505    
1506     /* Here: 1.0 <= nf < 2.0 */
1507     /* fatal(" nf=%f", nf); */
1508     nf -= 1.0; /* remove implicit first bit */
1509     for (i=n_frac-1; i>=0; i--) {
1510     nf *= 2.0;
1511     if (nf >= 1.0) {
1512     r |= ((uint64_t)1 << i);
1513     nf -= 1.0;
1514     }
1515     /* printf("\n i=%2i r=%016llx\n", i, (long long)r); */
1516     }
1517    
1518     /* Insert the exponent into the resulting word: */
1519     /* (First bias, then make sure it's within range) */
1520     exponent += (((uint64_t)1 << (n_exp-1)) - 1);
1521     if (exponent < 0)
1522     exponent = 0;
1523     if (exponent >= ((int64_t)1 << n_exp))
1524     exponent = ((int64_t)1 << n_exp) - 1;
1525     r |= (uint64_t)exponent << n_frac;
1526    
1527     /* Special case for 0.0: */
1528     if (exponent == 0)
1529     r = 0;
1530    
1531     /* fatal(" exp=%i, r = %016llx\n", exponent, (long long)r); */
1532    
1533     break;
1534     default:
1535     /* TODO */
1536     fatal("fpu_store_float_value(): unimplemented format "
1537     "%i\n", fmt);
1538     }
1539    
1540     store_nan:
1541     if (nan) {
1542     if (fmt == FMT_S)
1543     r = 0x7fffffffULL;
1544     else if (fmt == FMT_D)
1545     r = 0x7fffffffffffffffULL;
1546     else
1547     r = 0x7fffffffULL;
1548     }
1549    
1550     /*
1551     * TODO: this is for 32-bit mode. It has to be updated later
1552     * for 64-bit coprocessor stuff.
1553     */
1554     if (fmt == FMT_D || fmt == FMT_L) {
1555     cp->reg[fd] = r & 0xffffffffULL;
1556     cp->reg[(fd+1) & 31] = (r >> 32) & 0xffffffffULL;
1557    
1558     if (cp->reg[fd] & 0x80000000ULL)
1559     cp->reg[fd] |= 0xffffffff00000000ULL;
1560     if (cp->reg[fd+1] & 0x80000000ULL)
1561     cp->reg[fd+1] |= 0xffffffff00000000ULL;
1562     } else {
1563     cp->reg[fd] = r & 0xffffffffULL;
1564    
1565     if (cp->reg[fd] & 0x80000000ULL)
1566     cp->reg[fd] |= 0xffffffff00000000ULL;
1567     }
1568     }
1569    
1570    
1571     /*
1572     * fpu_op():
1573     *
1574     * Perform a floating-point operation. For those of fs and ft
1575     * that are >= 0, those numbers are interpreted into local
1576     * variables.
1577     *
1578     * Only FPU_OP_C (compare) returns anything of interest, 1 for
1579     * true, 0 for false.
1580     */
1581     static int fpu_op(struct cpu *cpu, struct mips_coproc *cp, int op, int fmt,
1582     int ft, int fs, int fd, int cond, int output_fmt)
1583     {
1584     /* Potentially two input registers, fs and ft */
1585     struct internal_float_value float_value[2];
1586     int unordered, nan;
1587     uint64_t fs_v = 0;
1588     double nf;
1589    
1590     if (fs >= 0) {
1591     fs_v = cp->reg[fs];
1592     /* TODO: register-pair mode and plain
1593     register mode? "FR" bit? */
1594     if (fmt == FMT_D || fmt == FMT_L)
1595     fs_v = (fs_v & 0xffffffffULL) +
1596     (cp->reg[(fs + 1) & 31] << 32);
1597     fpu_interpret_float_value(fs_v, &float_value[0], fmt);
1598     }
1599     if (ft >= 0) {
1600     uint64_t v = cp->reg[ft];
1601     /* TODO: register-pair mode and
1602     plain register mode? "FR" bit? */
1603     if (fmt == FMT_D || fmt == FMT_L)
1604     v = (v & 0xffffffffULL) +
1605     (cp->reg[(ft + 1) & 31] << 32);
1606     fpu_interpret_float_value(v, &float_value[1], fmt);
1607     }
1608    
1609     switch (op) {
1610     case FPU_OP_ADD:
1611     nf = float_value[0].f + float_value[1].f;
1612     /* debug(" add: %f + %f = %f\n",
1613     float_value[0].f, float_value[1].f, nf); */
1614     fpu_store_float_value(cp, fd, nf, output_fmt,
1615     float_value[0].nan || float_value[1].nan);
1616     break;
1617     case FPU_OP_SUB:
1618     nf = float_value[0].f - float_value[1].f;
1619     /* debug(" sub: %f - %f = %f\n",
1620     float_value[0].f, float_value[1].f, nf); */
1621     fpu_store_float_value(cp, fd, nf, output_fmt,
1622     float_value[0].nan || float_value[1].nan);
1623     break;
1624     case FPU_OP_MUL:
1625     nf = float_value[0].f * float_value[1].f;
1626     /* debug(" mul: %f * %f = %f\n",
1627     float_value[0].f, float_value[1].f, nf); */
1628     fpu_store_float_value(cp, fd, nf, output_fmt,
1629     float_value[0].nan || float_value[1].nan);
1630     break;
1631     case FPU_OP_DIV:
1632     nan = float_value[0].nan || float_value[1].nan;
1633     if (fabs(float_value[1].f) > 0.00000000001)
1634     nf = float_value[0].f / float_value[1].f;
1635     else {
1636     fatal("DIV by zero !!!!\n");
1637     nf = 0.0; /* TODO */
1638     nan = 1;
1639     }
1640     /* debug(" div: %f / %f = %f\n",
1641     float_value[0].f, float_value[1].f, nf); */
1642     fpu_store_float_value(cp, fd, nf, output_fmt, nan);
1643     break;
1644     case FPU_OP_SQRT:
1645     nan = float_value[0].nan;
1646     if (float_value[0].f >= 0.0)
1647     nf = sqrt(float_value[0].f);
1648     else {
1649     fatal("SQRT by less than zero, %f !!!!\n",
1650     float_value[0].f);
1651     nf = 0.0; /* TODO */
1652     nan = 1;
1653     }
1654     /* debug(" sqrt: %f => %f\n", float_value[0].f, nf); */
1655     fpu_store_float_value(cp, fd, nf, output_fmt, nan);
1656     break;
1657     case FPU_OP_ABS:
1658     nf = fabs(float_value[0].f);
1659     /* debug(" abs: %f => %f\n", float_value[0].f, nf); */
1660     fpu_store_float_value(cp, fd, nf, output_fmt,
1661     float_value[0].nan);
1662     break;
1663     case FPU_OP_NEG:
1664     nf = - float_value[0].f;
1665     /* debug(" neg: %f => %f\n", float_value[0].f, nf); */
1666     fpu_store_float_value(cp, fd, nf, output_fmt,
1667     float_value[0].nan);
1668     break;
1669     case FPU_OP_CVT:
1670     nf = float_value[0].f;
1671     /* debug(" mov: %f => %f\n", float_value[0].f, nf); */
1672     fpu_store_float_value(cp, fd, nf, output_fmt,
1673     float_value[0].nan);
1674     break;
1675     case FPU_OP_MOV:
1676     /* Non-arithmetic move: */
1677     /*
1678     * TODO: this is for 32-bit mode. It has to be updated later
1679     * for 64-bit coprocessor stuff.
1680     */
1681     if (output_fmt == FMT_D || output_fmt == FMT_L) {
1682     cp->reg[fd] = fs_v & 0xffffffffULL;
1683     cp->reg[(fd+1) & 31] = (fs_v >> 32) & 0xffffffffULL;
1684     if (cp->reg[fd] & 0x80000000ULL)
1685     cp->reg[fd] |= 0xffffffff00000000ULL;
1686     if (cp->reg[fd+1] & 0x80000000ULL)
1687     cp->reg[fd+1] |= 0xffffffff00000000ULL;
1688     } else {
1689     cp->reg[fd] = fs_v & 0xffffffffULL;
1690     if (cp->reg[fd] & 0x80000000ULL)
1691     cp->reg[fd] |= 0xffffffff00000000ULL;
1692     }
1693     break;
1694     case FPU_OP_C:
1695     /* debug(" c: cond=%i\n", cond); */
1696    
1697     unordered = 0;
1698     if (float_value[0].nan || float_value[1].nan)
1699     unordered = 1;
1700    
1701     switch (cond) {
1702     case 2: /* Equal */
1703     return (float_value[0].f == float_value[1].f);
1704     case 4: /* Ordered or Less than */
1705     return (float_value[0].f < float_value[1].f)
1706     || !unordered;
1707     case 5: /* Unordered or Less than */
1708     return (float_value[0].f < float_value[1].f)
1709     || unordered;
1710     case 6: /* Ordered or Less than or Equal */
1711     return (float_value[0].f <= float_value[1].f)
1712     || !unordered;
1713     case 7: /* Unordered or Less than or Equal */
1714     return (float_value[0].f <= float_value[1].f)
1715     || unordered;
1716     case 12:/* Less than */
1717     return (float_value[0].f < float_value[1].f);
1718     case 14:/* Less than or equal */
1719     return (float_value[0].f <= float_value[1].f);
1720    
1721     /* The following are not commonly used, so I'll move these out
1722     of the if-0 on a case-by-case basis. */
1723     #if 0
1724     case 0: return 0; /* False */
1725     case 1: return 0; /* Unordered */
1726     case 3: return (float_value[0].f == float_value[1].f);
1727     /* Unordered or Equal */
1728     case 8: return 0; /* Signaling false */
1729     case 9: return 0; /* Not Greater than or Less than or Equal */
1730     case 10:return (float_value[0].f == float_value[1].f); /* Signaling Equal */
1731     case 11:return (float_value[0].f == float_value[1].f); /* Not Greater
1732     than or Less than */
1733     case 13:return !(float_value[0].f >= float_value[1].f); /* Not greater
1734     than or equal */
1735     case 15:return !(float_value[0].f > float_value[1].f); /* Not greater than */
1736     #endif
1737    
1738     default:
1739     fatal("fpu_op(): unimplemented condition "
1740     "code %i. see cpu_mips_coproc.c\n", cond);
1741     }
1742     break;
1743     default:
1744     fatal("fpu_op(): unimplemented op %i\n", op);
1745     }
1746    
1747     return 0;
1748     }
1749    
1750    
1751     /*
1752     * fpu_function():
1753     *
1754     * Returns 1 if function was implemented, 0 otherwise.
1755     * Debug trace should be printed for known instructions.
1756     */
1757     static int fpu_function(struct cpu *cpu, struct mips_coproc *cp,
1758     uint32_t function, int unassemble_only)
1759     {
1760     int fd, fs, ft, fmt, cond, cc;
1761    
1762     fmt = (function >> 21) & 31;
1763     ft = (function >> 16) & 31;
1764     fs = (function >> 11) & 31;
1765     cc = (function >> 8) & 7;
1766     fd = (function >> 6) & 31;
1767     cond = (function >> 0) & 15;
1768    
1769    
1770     /* bc1f, bc1t, bc1fl, bc1tl: */
1771     if ((function & 0x03e00000) == 0x01000000) {
1772     int nd, tf, imm, cond_true;
1773     char *instr_mnem;
1774    
1775     /* cc are bits 20..18: */
1776     cc = (function >> 18) & 7;
1777     nd = (function >> 17) & 1;
1778     tf = (function >> 16) & 1;
1779     imm = function & 65535;
1780     if (imm >= 32768)
1781     imm -= 65536;
1782    
1783     instr_mnem = NULL;
1784     if (nd == 0 && tf == 0) instr_mnem = "bc1f";
1785     if (nd == 0 && tf == 1) instr_mnem = "bc1t";
1786     if (nd == 1 && tf == 0) instr_mnem = "bc1fl";
1787     if (nd == 1 && tf == 1) instr_mnem = "bc1tl";
1788    
1789     if (cpu->machine->instruction_trace || unassemble_only)
1790     debug("%s\t%i,0x%016llx\n", instr_mnem, cc,
1791     (long long) (cpu->pc + (imm << 2)));
1792     if (unassemble_only)
1793     return 1;
1794    
1795     if (cpu->cd.mips.delay_slot) {
1796     fatal("%s: jump inside a jump's delay slot, "
1797     "or similar. TODO\n", instr_mnem);
1798     cpu->running = 0;
1799     return 1;
1800     }
1801    
1802     /* Both the FCCR and FCSR contain condition code bits... */
1803     if (cc == 0)
1804     cond_true = (cp->fcr[FPU_FCSR] >> FCSR_FCC0_SHIFT) & 1;
1805     else
1806     cond_true = (cp->fcr[FPU_FCSR] >>
1807     (FCSR_FCC1_SHIFT + cc-1)) & 1;
1808    
1809     if (!tf)
1810     cond_true = !cond_true;
1811    
1812     if (cond_true) {
1813     cpu->cd.mips.delay_slot = TO_BE_DELAYED;
1814     cpu->cd.mips.delay_jmpaddr = cpu->pc + (imm << 2);
1815     } else {
1816     /* "likely": */
1817     if (nd) {
1818     /* nullify the delay slot */
1819     cpu->cd.mips.nullify_next = 1;
1820     }
1821     }
1822    
1823     return 1;
1824     }
1825    
1826     /* add.fmt: Floating-point add */
1827     if ((function & 0x0000003f) == 0x00000000) {
1828     if (cpu->machine->instruction_trace || unassemble_only)
1829     debug("add.%i\tr%i,r%i,r%i\n", fmt, fd, fs, ft);
1830     if (unassemble_only)
1831     return 1;
1832    
1833     fpu_op(cpu, cp, FPU_OP_ADD, fmt, ft, fs, fd, -1, fmt);
1834     return 1;
1835     }
1836    
1837     /* sub.fmt: Floating-point subtract */
1838     if ((function & 0x0000003f) == 0x00000001) {
1839     if (cpu->machine->instruction_trace || unassemble_only)
1840     debug("sub.%i\tr%i,r%i,r%i\n", fmt, fd, fs, ft);
1841     if (unassemble_only)
1842     return 1;
1843    
1844     fpu_op(cpu, cp, FPU_OP_SUB, fmt, ft, fs, fd, -1, fmt);
1845     return 1;
1846     }
1847    
1848     /* mul.fmt: Floating-point multiply */
1849     if ((function & 0x0000003f) == 0x00000002) {
1850     if (cpu->machine->instruction_trace || unassemble_only)
1851     debug("mul.%i\tr%i,r%i,r%i\n", fmt, fd, fs, ft);
1852     if (unassemble_only)
1853     return 1;
1854    
1855     fpu_op(cpu, cp, FPU_OP_MUL, fmt, ft, fs, fd, -1, fmt);
1856     return 1;
1857     }
1858    
1859     /* div.fmt: Floating-point divide */
1860     if ((function & 0x0000003f) == 0x00000003) {
1861     if (cpu->machine->instruction_trace || unassemble_only)
1862     debug("div.%i\tr%i,r%i,r%i\n", fmt, fd, fs, ft);
1863     if (unassemble_only)
1864     return 1;
1865    
1866     fpu_op(cpu, cp, FPU_OP_DIV, fmt, ft, fs, fd, -1, fmt);
1867     return 1;
1868     }
1869    
1870     /* sqrt.fmt: Floating-point square-root */
1871     if ((function & 0x001f003f) == 0x00000004) {
1872     if (cpu->machine->instruction_trace || unassemble_only)
1873     debug("sqrt.%i\tr%i,r%i\n", fmt, fd, fs);
1874     if (unassemble_only)
1875     return 1;
1876    
1877     fpu_op(cpu, cp, FPU_OP_SQRT, fmt, -1, fs, fd, -1, fmt);
1878     return 1;
1879     }
1880    
1881     /* abs.fmt: Floating-point absolute value */
1882     if ((function & 0x001f003f) == 0x00000005) {
1883     if (cpu->machine->instruction_trace || unassemble_only)
1884     debug("abs.%i\tr%i,r%i\n", fmt, fd, fs);
1885     if (unassemble_only)
1886     return 1;
1887    
1888     fpu_op(cpu, cp, FPU_OP_ABS, fmt, -1, fs, fd, -1, fmt);
1889     return 1;
1890     }
1891    
1892     /* mov.fmt: Floating-point (non-arithmetic) move */
1893     if ((function & 0x0000003f) == 0x00000006) {
1894     if (cpu->machine->instruction_trace || unassemble_only)
1895     debug("mov.%i\tr%i,r%i\n", fmt, fd, fs);
1896     if (unassemble_only)
1897     return 1;
1898    
1899     fpu_op(cpu, cp, FPU_OP_MOV, fmt, -1, fs, fd, -1, fmt);
1900     return 1;
1901     }
1902    
1903     /* neg.fmt: Floating-point negate */
1904     if ((function & 0x001f003f) == 0x00000007) {
1905     if (cpu->machine->instruction_trace || unassemble_only)
1906     debug("neg.%i\tr%i,r%i\n", fmt, fd, fs);
1907     if (unassemble_only)
1908     return 1;
1909    
1910     fpu_op(cpu, cp, FPU_OP_NEG, fmt, -1, fs, fd, -1, fmt);
1911     return 1;
1912     }
1913    
1914     /* trunc.l.fmt: Truncate */
1915     if ((function & 0x001f003f) == 0x00000009) {
1916     if (cpu->machine->instruction_trace || unassemble_only)
1917     debug("trunc.l.%i\tr%i,r%i\n", fmt, fd, fs);
1918     if (unassemble_only)
1919     return 1;
1920    
1921     /* TODO: not CVT? */
1922    
1923     fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, FMT_L);
1924     return 1;
1925     }
1926    
1927     /* trunc.w.fmt: Truncate */
1928     if ((function & 0x001f003f) == 0x0000000d) {
1929     if (cpu->machine->instruction_trace || unassemble_only)
1930     debug("trunc.w.%i\tr%i,r%i\n", fmt, fd, fs);
1931     if (unassemble_only)
1932     return 1;
1933    
1934     /* TODO: not CVT? */
1935    
1936     fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, FMT_W);
1937     return 1;
1938     }
1939    
1940     /* c.cond.fmt: Floating-point compare */
1941     if ((function & 0x000000f0) == 0x00000030) {
1942     int cond_true;
1943     int bit;
1944    
1945     if (cpu->machine->instruction_trace || unassemble_only)
1946     debug("c.%i.%i\tr%i,r%i,r%i\n", cond, fmt, cc, fs, ft);
1947     if (unassemble_only)
1948     return 1;
1949    
1950     cond_true = fpu_op(cpu, cp, FPU_OP_C, fmt,
1951     ft, fs, -1, cond, fmt);
1952    
1953     /*
1954     * Both the FCCR and FCSR contain condition code bits:
1955     * FCCR: bits 7..0
1956     * FCSR: bits 31..25 and 23
1957     */
1958     cp->fcr[FPU_FCCR] &= ~(1 << cc);
1959     if (cond_true)
1960     cp->fcr[FPU_FCCR] |= (1 << cc);
1961    
1962     if (cc == 0) {
1963     bit = 1 << FCSR_FCC0_SHIFT;
1964     cp->fcr[FPU_FCSR] &= ~bit;
1965     if (cond_true)
1966     cp->fcr[FPU_FCSR] |= bit;
1967     } else {
1968     bit = 1 << (FCSR_FCC1_SHIFT + cc-1);
1969     cp->fcr[FPU_FCSR] &= ~bit;
1970     if (cond_true)
1971     cp->fcr[FPU_FCSR] |= bit;
1972     }
1973    
1974     return 1;
1975     }
1976    
1977     /* cvt.s.fmt: Convert to single floating-point */
1978     if ((function & 0x001f003f) == 0x00000020) {
1979     if (cpu->machine->instruction_trace || unassemble_only)
1980     debug("cvt.s.%i\tr%i,r%i\n", fmt, fd, fs);
1981     if (unassemble_only)
1982     return 1;
1983    
1984     fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, FMT_S);
1985     return 1;
1986     }
1987    
1988     /* cvt.d.fmt: Convert to double floating-point */
1989     if ((function & 0x001f003f) == 0x00000021) {
1990     if (cpu->machine->instruction_trace || unassemble_only)
1991     debug("cvt.d.%i\tr%i,r%i\n", fmt, fd, fs);
1992     if (unassemble_only)
1993     return 1;
1994    
1995     fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, FMT_D);
1996     return 1;
1997     }
1998    
1999     /* cvt.w.fmt: Convert to word fixed-point */
2000     if ((function & 0x001f003f) == 0x00000024) {
2001     if (cpu->machine->instruction_trace || unassemble_only)
2002     debug("cvt.w.%i\tr%i,r%i\n", fmt, fd, fs);
2003     if (unassemble_only)
2004     return 1;
2005    
2006     fpu_op(cpu, cp, FPU_OP_CVT, fmt, -1, fs, fd, -1, FMT_W);
2007     return 1;
2008     }
2009    
2010     return 0;
2011     }
2012    
2013    
2014     /*
2015     * coproc_tlbpr():
2016     *
2017     * 'tlbp' and 'tlbr'.
2018     */
2019     void coproc_tlbpr(struct cpu *cpu, int readflag)
2020     {
2021     struct mips_coproc *cp = cpu->cd.mips.coproc[0];
2022     int i, found, g_bit;
2023     uint64_t vpn2, xmask;
2024    
2025     /* Read: */
2026     if (readflag) {
2027     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
2028     i = (cp->reg[COP0_INDEX] & R2K3K_INDEX_MASK) >>
2029     R2K3K_INDEX_SHIFT;
2030     if (i >= cp->nr_of_tlbs) {
2031     /* TODO: exception? */
2032     fatal("warning: tlbr from index %i (too "
2033     "high)\n", i);
2034     return;
2035     }
2036    
2037     /*
2038     * TODO: Hm. Earlier I had an & ~0x3f on the high
2039     * assignment and an & ~0xff on the lo0 assignment.
2040     * I wonder why.
2041     */
2042    
2043     cp->reg[COP0_ENTRYHI] = cp->tlbs[i].hi; /* & ~0x3f; */
2044     cp->reg[COP0_ENTRYLO0] = cp->tlbs[i].lo0;/* & ~0xff; */
2045     } else {
2046     /* R4000: */
2047     i = cp->reg[COP0_INDEX] & INDEX_MASK;
2048     if (i >= cp->nr_of_tlbs) /* TODO: exception */
2049     return;
2050    
2051     cp->reg[COP0_PAGEMASK] = cp->tlbs[i].mask;
2052     cp->reg[COP0_ENTRYHI] = cp->tlbs[i].hi;
2053     cp->reg[COP0_ENTRYLO1] = cp->tlbs[i].lo1;
2054     cp->reg[COP0_ENTRYLO0] = cp->tlbs[i].lo0;
2055    
2056     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
2057     /* R4100 don't have the G bit in entryhi */
2058     } else {
2059     /* R4000 etc: */
2060     cp->reg[COP0_ENTRYHI] &= ~TLB_G;
2061     g_bit = cp->tlbs[i].hi & TLB_G;
2062    
2063     cp->reg[COP0_ENTRYLO0] &= ~ENTRYLO_G;
2064     cp->reg[COP0_ENTRYLO1] &= ~ENTRYLO_G;
2065     if (g_bit) {
2066     cp->reg[COP0_ENTRYLO0] |= ENTRYLO_G;
2067     cp->reg[COP0_ENTRYLO1] |= ENTRYLO_G;
2068     }
2069     }
2070     }
2071    
2072     return;
2073     }
2074    
2075     /* Probe: */
2076     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
2077     vpn2 = cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_VPN_MASK;
2078     found = -1;
2079     for (i=0; i<cp->nr_of_tlbs; i++)
2080     if ( ((cp->tlbs[i].hi & R2K3K_ENTRYHI_ASID_MASK) ==
2081     (cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_ASID_MASK))
2082     || cp->tlbs[i].lo0 & R2K3K_ENTRYLO_G)
2083     if ((cp->tlbs[i].hi & R2K3K_ENTRYHI_VPN_MASK)
2084     == vpn2) {
2085     found = i;
2086     break;
2087     }
2088     } else {
2089     /* R4000 and R10000: */
2090     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
2091     xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K;
2092     else if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
2093     xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK | 0x1800;
2094     else
2095     xmask = ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK;
2096     vpn2 = cp->reg[COP0_ENTRYHI] & xmask;
2097     found = -1;
2098     for (i=0; i<cp->nr_of_tlbs; i++) {
2099     int gbit = cp->tlbs[i].hi & TLB_G;
2100     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
2101     gbit = (cp->tlbs[i].lo0 & ENTRYLO_G) &&
2102     (cp->tlbs[i].lo1 & ENTRYLO_G);
2103    
2104     if ( ((cp->tlbs[i].hi & ENTRYHI_ASID) ==
2105     (cp->reg[COP0_ENTRYHI] & ENTRYHI_ASID)) || gbit) {
2106     uint64_t a = vpn2 & ~cp->tlbs[i].mask;
2107     uint64_t b = (cp->tlbs[i].hi & xmask) &
2108     ~cp->tlbs[i].mask;
2109     if (a == b) {
2110     found = i;
2111     break;
2112     }
2113     }
2114     }
2115     }
2116     if (found == -1)
2117     cp->reg[COP0_INDEX] = INDEX_P;
2118     else {
2119     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
2120     cp->reg[COP0_INDEX] = found << R2K3K_INDEX_SHIFT;
2121     else
2122     cp->reg[COP0_INDEX] = found;
2123     }
2124    
2125     /* Sign extend the index register: */
2126     if ((cp->reg[COP0_INDEX] >> 32) == 0 &&
2127     cp->reg[COP0_INDEX] & 0x80000000)
2128     cp->reg[COP0_INDEX] |=
2129     0xffffffff00000000ULL;
2130     }
2131    
2132    
2133     /*
2134     * coproc_tlbwri():
2135     *
2136     * 'tlbwr' and 'tlbwi'
2137     */
2138     void coproc_tlbwri(struct cpu *cpu, int randomflag)
2139     {
2140     struct mips_coproc *cp = cpu->cd.mips.coproc[0];
2141     int index, g_bit;
2142     uint64_t oldvaddr;
2143     int old_asid = -1;
2144    
2145     /*
2146     * ... and the last instruction page:
2147     *
2148     * Some thoughts about this: Code running in
2149     * the kernel's physical address space has the
2150     * same vaddr->paddr translation, so the last
2151     * virtual page invalidation only needs to
2152     * happen if we are for some extremely weird
2153     * reason NOT running in the kernel's physical
2154     * address space.
2155     *
2156     * (An even insaner (but probably useless)
2157     * optimization would be to only invalidate
2158     * the last virtual page stuff if the TLB
2159     * update actually affects the vaddr in
2160     * question.)
2161     */
2162    
2163     if (cpu->pc < (uint64_t)0xffffffff80000000ULL ||
2164     cpu->pc >= (uint64_t)0xffffffffc0000000ULL)
2165     cpu->cd.mips.pc_last_virtual_page =
2166     PC_LAST_PAGE_IMPOSSIBLE_VALUE;
2167    
2168     if (randomflag) {
2169     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
2170     index = (cp->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
2171     >> R2K3K_RANDOM_SHIFT;
2172     else
2173     index = cp->reg[COP0_RANDOM] & RANDOM_MASK;
2174     } else {
2175     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K)
2176     index = (cp->reg[COP0_INDEX] & R2K3K_INDEX_MASK)
2177     >> R2K3K_INDEX_SHIFT;
2178     else
2179     index = cp->reg[COP0_INDEX] & INDEX_MASK;
2180     }
2181    
2182     if (index >= cp->nr_of_tlbs) {
2183     fatal("warning: tlb index %i too high (max is %i)\n",
2184     index, cp->nr_of_tlbs - 1);
2185     /* TODO: cause an exception? */
2186     return;
2187     }
2188    
2189     #if 0
2190     /* Debug dump of the previous entry at that index: */
2191     debug(" old entry at index = %04x", index);
2192     debug(" mask = %016llx", (long long) cp->tlbs[index].mask);
2193     debug(" hi = %016llx", (long long) cp->tlbs[index].hi);
2194     debug(" lo0 = %016llx", (long long) cp->tlbs[index].lo0);
2195     debug(" lo1 = %016llx\n", (long long) cp->tlbs[index].lo1);
2196     #endif
2197    
2198     /* Translation caches must be invalidated: */
2199     switch (cpu->cd.mips.cpu_type.mmu_model) {
2200     case MMU3K:
2201     oldvaddr = cp->tlbs[index].hi & R2K3K_ENTRYHI_VPN_MASK;
2202     oldvaddr &= 0xffffffffULL;
2203     if (oldvaddr & 0x80000000ULL)
2204     oldvaddr |= 0xffffffff00000000ULL;
2205     old_asid = (cp->tlbs[index].hi & R2K3K_ENTRYHI_ASID_MASK)
2206     >> R2K3K_ENTRYHI_ASID_SHIFT;
2207    
2208     /* TODO: Bug? Why does this if need to be commented out? */
2209    
2210     /* if (cp->tlbs[index].lo0 & ENTRYLO_V) */
2211     invalidate_translation_caches(cpu, 0, oldvaddr, 0, 0);
2212     break;
2213     default:
2214     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) {
2215     oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK_R10K;
2216     /* 44 addressable bits: */
2217     if (oldvaddr & 0x80000000000ULL)
2218     oldvaddr |= 0xfffff00000000000ULL;
2219     } else {
2220     /* Assume MMU4K */
2221     oldvaddr = cp->tlbs[index].hi & ENTRYHI_VPN2_MASK;
2222     /* 40 addressable bits: */
2223     if (oldvaddr & 0x8000000000ULL)
2224     oldvaddr |= 0xffffff0000000000ULL;
2225     }
2226    
2227     /*
2228     * Both pages:
2229     *
2230     * TODO: non-4KB page sizes!
2231     */
2232     invalidate_translation_caches(
2233     cpu, 0, oldvaddr & ~0x1fff, 0, 0);
2234     invalidate_translation_caches(
2235     cpu, 0, (oldvaddr & ~0x1fff) | 0x1000, 0, 0);
2236     }
2237    
2238    
2239     /* Write the new entry: */
2240    
2241     if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) {
2242     uint64_t vaddr, paddr;
2243     int wf = cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_D? 1 : 0;
2244     unsigned char *memblock = NULL;
2245    
2246     cp->tlbs[index].hi = cp->reg[COP0_ENTRYHI];
2247     cp->tlbs[index].lo0 = cp->reg[COP0_ENTRYLO0];
2248    
2249     vaddr = cp->reg[COP0_ENTRYHI] & R2K3K_ENTRYHI_VPN_MASK;
2250     paddr = cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_PFN_MASK;
2251    
2252     /* TODO: This is ugly. */
2253     if (paddr < 0x10000000)
2254     memblock = memory_paddr_to_hostaddr(
2255     cpu->mem, paddr, 1);
2256    
2257     if (memblock != NULL &&
2258     cp->reg[COP0_ENTRYLO0] & R2K3K_ENTRYLO_V) {
2259     memblock += (paddr & ((1 << BITS_PER_PAGETABLE) - 1));
2260    
2261     /*
2262     * TODO: Hahaha, this is even uglier than the thing
2263     * above. Some OSes seem to map code pages read/write,
2264     * which causes the bintrans cache to be invalidated
2265     * even when it doesn't have to be.
2266     */
2267     /* if (vaddr < 0x10000000) */
2268     wf = 0;
2269    
2270     update_translation_table(cpu, vaddr, memblock,
2271     wf, paddr);
2272     }
2273     } else {
2274     /* R4000: */
2275     g_bit = (cp->reg[COP0_ENTRYLO0] &
2276     cp->reg[COP0_ENTRYLO1]) & ENTRYLO_G;
2277     cp->tlbs[index].mask = cp->reg[COP0_PAGEMASK];
2278     cp->tlbs[index].hi = cp->reg[COP0_ENTRYHI];
2279     cp->tlbs[index].lo1 = cp->reg[COP0_ENTRYLO1];
2280     cp->tlbs[index].lo0 = cp->reg[COP0_ENTRYLO0];
2281    
2282     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
2283     /* NOTE: The VR4131 (and possibly others) don't have
2284     a Global bit in entryhi */
2285     cp->tlbs[index].hi &= ~cp->reg[COP0_PAGEMASK];
2286     } else {
2287     cp->tlbs[index].lo0 &= ~ENTRYLO_G;
2288     cp->tlbs[index].lo1 &= ~ENTRYLO_G;
2289    
2290     cp->tlbs[index].hi &= ~TLB_G;
2291     if (g_bit)
2292     cp->tlbs[index].hi |= TLB_G;
2293     }
2294     }
2295    
2296     if (randomflag) {
2297     if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
2298     cp->reg[COP0_RANDOM] =
2299     ((random() % (cp->nr_of_tlbs - 8)) + 8)
2300     << R2K3K_RANDOM_SHIFT;
2301     } else {
2302     cp->reg[COP0_RANDOM] = cp->reg[COP0_WIRED] + (random()
2303     % (cp->nr_of_tlbs - cp->reg[COP0_WIRED]));
2304     }
2305     }
2306     }
2307    
2308    
2309     /*
2310     * coproc_rfe():
2311     *
2312     * Return from exception. (R3000 etc.)
2313     */
2314     void coproc_rfe(struct cpu *cpu)
2315     {
2316     int oldmode;
2317    
2318     oldmode = cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & MIPS1_SR_KU_CUR;
2319    
2320     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
2321     (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
2322     ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);
2323    
2324     /* Changing from kernel to user mode? Then this is necessary: */
2325     if (!oldmode &&
2326     (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &
2327     MIPS1_SR_KU_CUR))
2328     invalidate_translation_caches(cpu, 0, 0, 1, 0);
2329     }
2330    
2331    
2332     /*
2333     * coproc_eret():
2334     *
2335     * Return from exception. (R4000 etc.)
2336     */
2337     void coproc_eret(struct cpu *cpu)
2338     {
2339     int oldmode, newmode;
2340    
2341     /* Kernel mode flag: */
2342     oldmode = 0;
2343     if ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & MIPS3_SR_KSU_MASK)
2344     != MIPS3_SR_KSU_USER
2345     || (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & (STATUS_EXL |
2346     STATUS_ERL)) ||
2347     (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 1) == 0)
2348     oldmode = 1;
2349    
2350     if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
2351     cpu->pc = cpu->cd.mips.pc_last =
2352     cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
2353     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
2354     } else {
2355     cpu->pc = cpu->cd.mips.pc_last =
2356     cpu->cd.mips.coproc[0]->reg[COP0_EPC];
2357     cpu->cd.mips.delay_slot = 0;
2358     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
2359     }
2360    
2361     cpu->cd.mips.rmw = 0; /* the "LL bit" */
2362    
2363     /* New kernel mode flag: */
2364     newmode = 0;
2365     if ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & MIPS3_SR_KSU_MASK)
2366     != MIPS3_SR_KSU_USER
2367     || (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & (STATUS_EXL |
2368     STATUS_ERL)) ||
2369     (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 1) == 0)
2370     newmode = 1;
2371    
2372     /* Changing from kernel to user mode?
2373     Then this is necessary: TODO */
2374     if (oldmode && !newmode)
2375     invalidate_translation_caches(cpu, 0, 0, 1, 0);
2376     }
2377    
2378    
2379     /*
2380     * coproc_function():
2381     *
2382     * Execute a coprocessor specific instruction. cp must be != NULL.
2383     * Debug trace should be printed for known instructions, if
2384     * unassemble_only is non-zero. (This will NOT execute the instruction.)
2385     *
2386     * TODO: This is a mess and should be restructured (again).
2387     */
2388     void coproc_function(struct cpu *cpu, struct mips_coproc *cp, int cpnr,
2389     uint32_t function, int unassemble_only, int running)
2390     {
2391     int co_bit, op, rt, rd, fs, copz;
2392     uint64_t tmpvalue;
2393    
2394     if (cp == NULL) {
2395     if (unassemble_only) {
2396     debug("cop%i\t0x%08x (coprocessor not available)\n",
2397     cpnr, (int)function);
2398     return;
2399     }
2400     fatal("[ pc=0x%016llx cop%i\t0x%08x (coprocessor not "
2401     "available)\n", (long long)cpu->pc, cpnr, (int)function);
2402     return;
2403     }
2404    
2405     #if 0
2406     /* No FPU? */
2407     if (cpnr == 1 && (cpu->cd.mips.cpu_type.flags & NOFPU)) {
2408     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2409     return;
2410     }
2411     #endif
2412    
2413     /* For quick reference: */
2414     copz = (function >> 21) & 31;
2415     rt = (function >> 16) & 31;
2416     rd = (function >> 11) & 31;
2417    
2418     if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MFCz << 21))
2419     || ((function & 0x03e007f8) == (COPz_DMFCz << 21)))) {
2420     if (unassemble_only) {
2421     debug("%s%i\t%s,%s\n",
2422     copz==COPz_DMFCz? "dmfc" : "mfc", cpnr,
2423     regnames[rt], cop0_names[rd]);
2424     return;
2425     }
2426     coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr],
2427     rd, &tmpvalue);
2428     cpu->cd.mips.gpr[rt] = tmpvalue;
2429     if (copz == COPz_MFCz) {
2430     /* Sign-extend: */
2431     cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
2432     if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
2433     cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
2434     }
2435     return;
2436     }
2437    
2438     if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MTCz << 21))
2439     || ((function & 0x03e007f8) == (COPz_DMTCz << 21)))) {
2440     if (unassemble_only) {
2441     debug("%s%i\t%s,%s\n",
2442     copz==COPz_DMTCz? "dmtc" : "mtc", cpnr,
2443     regnames[rt], cop0_names[rd]);
2444     return;
2445     }
2446     tmpvalue = cpu->cd.mips.gpr[rt];
2447     if (copz == COPz_MTCz) {
2448     /* Sign-extend: */
2449     tmpvalue &= 0xffffffffULL;
2450     if (tmpvalue & 0x80000000ULL)
2451     tmpvalue |= 0xffffffff00000000ULL;
2452     }
2453     coproc_register_write(cpu, cpu->cd.mips.coproc[cpnr], rd,
2454     &tmpvalue, copz == COPz_DMTCz);
2455     return;
2456     }
2457    
2458     if (cpnr <= 1 && (((function & 0x03e007ff) == (COPz_CFCz << 21))
2459     || ((function & 0x03e007ff) == (COPz_CTCz << 21)))) {
2460     switch (copz) {
2461     case COPz_CFCz: /* Copy from FPU control register */
2462     rt = (function >> 16) & 31;
2463     fs = (function >> 11) & 31;
2464     if (unassemble_only) {
2465     debug("cfc%i\t%s,r%i\n", cpnr,
2466     regnames[rt], fs);
2467     return;
2468     }
2469     cpu->cd.mips.gpr[rt] = cp->fcr[fs] & 0xffffffffULL;
2470     if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
2471     cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
2472     /* TODO: implement delay for gpr[rt]
2473     (for MIPS I,II,III only) */
2474     return;
2475     case COPz_CTCz: /* Copy to FPU control register */
2476     rt = (function >> 16) & 31;
2477     fs = (function >> 11) & 31;
2478     if (unassemble_only) {
2479     debug("ctc%i\t%s,r%i\n", cpnr,
2480     regnames[rt], fs);
2481     return;
2482     }
2483    
2484     switch (cpnr) {
2485     case 0: /* System coprocessor */
2486     fatal("[ warning: unimplemented ctc%i, "
2487     "0x%08x -> ctl reg %i ]\n", cpnr,
2488     (int)cpu->cd.mips.gpr[rt], fs);
2489     break;
2490     case 1: /* FPU */
2491     if (fs == 0)
2492     fatal("[ Attempt to write to FPU "
2493     "control register 0 (?) ]\n");
2494     else {
2495     uint64_t tmp = cpu->cd.mips.gpr[rt];
2496     cp->fcr[fs] = tmp;
2497    
2498     /* TODO: writing to control register 31
2499     should cause exceptions, depending
2500     on status bits! */
2501    
2502     switch (fs) {
2503     case FPU_FCCR:
2504     cp->fcr[FPU_FCSR] =
2505     (cp->fcr[FPU_FCSR] &
2506     0x017fffffULL) | ((tmp & 1)
2507     << FCSR_FCC0_SHIFT)
2508     | (((tmp & 0xfe) >> 1) <<
2509     FCSR_FCC1_SHIFT);
2510     break;
2511     case FPU_FCSR:
2512     cp->fcr[FPU_FCCR] =
2513     (cp->fcr[FPU_FCCR] &
2514     0xffffff00ULL) | ((tmp >>
2515     FCSR_FCC0_SHIFT) & 1) |
2516     (((tmp >> FCSR_FCC1_SHIFT)
2517     & 0x7f) << 1);
2518     break;
2519     default:
2520     ;
2521     }
2522     }
2523     break;
2524     }
2525    
2526     /* TODO: implement delay for gpr[rt]
2527     (for MIPS I,II,III only) */
2528     return;
2529     default:
2530     ;
2531     }
2532     }
2533    
2534     /* Math (Floating point) coprocessor calls: */
2535     if (cpnr==1) {
2536     if (fpu_function(cpu, cp, function, unassemble_only))
2537     return;
2538     }
2539    
2540     /* For AU1500 and probably others: deret */
2541     if (function == 0x0200001f) {
2542     if (unassemble_only) {
2543     debug("deret\n");
2544     return;
2545     }
2546    
2547     /*
2548     * According to the MIPS64 manual, deret loads PC from the
2549     * DEPC cop0 register, and jumps there immediately. No
2550     * delay slot.
2551     *
2552     * TODO: This instruction is only available if the processor
2553     * is in debug mode. (What does that mean?)
2554     * TODO: This instruction is undefined in a delay slot.
2555     */
2556    
2557     cpu->pc = cpu->cd.mips.pc_last = cp->reg[COP0_DEPC];
2558     cpu->cd.mips.delay_slot = 0;
2559     cp->reg[COP0_STATUS] &= ~STATUS_EXL;
2560    
2561     return;
2562     }
2563    
2564    
2565     /* Ugly R5900 hacks: */
2566     if ((function & 0xfffff) == 0x38) { /* ei */
2567     if (unassemble_only) {
2568     debug("ei\n");
2569     return;
2570     }
2571     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2572     return;
2573     }
2574    
2575     if ((function & 0xfffff) == 0x39) { /* di */
2576     if (unassemble_only) {
2577     debug("di\n");
2578     return;
2579     }
2580     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2581     return;
2582     }
2583    
2584     co_bit = (function >> 25) & 1;
2585    
2586     /* TLB operations and other things: */
2587     if (cp->coproc_nr == 0) {
2588     op = (function) & 0xff;
2589     switch (co_bit) {
2590     case 1:
2591     switch (op) {
2592     case COP0_TLBR: /* Read indexed TLB entry */
2593     if (unassemble_only) {
2594     debug("tlbr\n");
2595     return;
2596     }
2597     coproc_tlbpr(cpu, 1);
2598     return;
2599     case COP0_TLBWI: /* Write indexed */
2600     case COP0_TLBWR: /* Write random */
2601     if (unassemble_only) {
2602     if (op == COP0_TLBWI)
2603     debug("tlbwi");
2604     else
2605     debug("tlbwr");
2606     if (!running) {
2607     debug("\n");
2608     return;
2609     }
2610     debug("\tindex=%08llx",
2611     (long long)cp->reg[COP0_INDEX]);
2612     debug(", random=%08llx",
2613     (long long)cp->reg[COP0_RANDOM]);
2614     debug(", mask=%016llx",
2615     (long long)cp->reg[COP0_PAGEMASK]);
2616     debug(", hi=%016llx",
2617     (long long)cp->reg[COP0_ENTRYHI]);
2618     debug(", lo0=%016llx",
2619     (long long)cp->reg[COP0_ENTRYLO0]);
2620     debug(", lo1=%016llx\n",
2621     (long long)cp->reg[COP0_ENTRYLO1]);
2622     }
2623     coproc_tlbwri(cpu, op == COP0_TLBWR);
2624     return;
2625     case COP0_TLBP: /* Probe TLB for
2626     matching entry */
2627     if (unassemble_only) {
2628     debug("tlbp\n");
2629     return;
2630     }
2631     coproc_tlbpr(cpu, 0);
2632     return;
2633     case COP0_RFE: /* R2000/R3000 only:
2634     Return from Exception */
2635     if (unassemble_only) {
2636     debug("rfe\n");
2637     return;
2638     }
2639     coproc_rfe(cpu);
2640     return;
2641     case COP0_ERET: /* R4000: Return from exception */
2642     if (unassemble_only) {
2643     debug("eret\n");
2644     return;
2645     }
2646     coproc_eret(cpu);
2647     return;
2648     case COP0_STANDBY:
2649     if (unassemble_only) {
2650     debug("standby\n");
2651     return;
2652     }
2653     /* TODO: Hm. Do something here? */
2654     return;
2655     case COP0_SUSPEND:
2656     if (unassemble_only) {
2657     debug("suspend\n");
2658     return;
2659     }
2660     /* TODO: Hm. Do something here? */
2661     return;
2662     case COP0_HIBERNATE:
2663     if (unassemble_only) {
2664     debug("hibernate\n");
2665     return;
2666     }
2667     /* TODO: Hm. Do something here? */
2668     return;
2669     default:
2670     ;
2671     }
2672     default:
2673     ;
2674     }
2675     }
2676    
2677     /* TODO: coprocessor R2020 on DECstation? */
2678     if ((cp->coproc_nr==0 || cp->coproc_nr==3) && function == 0x0100ffff) {
2679     if (unassemble_only) {
2680     debug("decstation_r2020_writeback\n");
2681     return;
2682     }
2683     /* TODO */
2684     return;
2685     }
2686    
2687     /* TODO: RM5200 idle (?) */
2688     if ((cp->coproc_nr==0 || cp->coproc_nr==3) && function == 0x02000020) {
2689     if (unassemble_only) {
2690     debug("idle(?)\n"); /* TODO */
2691     return;
2692     }
2693    
2694     /* Idle? TODO */
2695     return;
2696     }
2697    
2698     if (unassemble_only) {
2699     debug("cop%i\t0x%08x (unimplemented)\n", cpnr, (int)function);
2700     return;
2701     }
2702    
2703     fatal("cpu%i: UNIMPLEMENTED coproc%i function %08lx "
2704     "(pc = %016llx)\n", cpu->cpu_id, cp->coproc_nr, function,
2705     (long long)cpu->cd.mips.pc_last);
2706     #if 1
2707     single_step = 1;
2708     #else
2709     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cp->coproc_nr, 0, 0, 0);
2710     #endif
2711     }
2712    
2713     #endif /* ENABLE_MIPS */

  ViewVC Help
Powered by ViewVC 1.1.26