/[gxemul]/trunk/src/cpu_ppc.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_ppc.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: 68845 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) 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_ppc.c,v 1.61 2005/04/01 16:44:36 debug Exp $
29     *
30     * PowerPC/POWER CPU emulation.
31     */
32    
33     #include <stdio.h>
34     #include <stdlib.h>
35     #include <string.h>
36     #include <ctype.h>
37    
38     #include "misc.h"
39    
40    
41     #ifndef ENABLE_PPC
42    
43    
44     #include "cpu_ppc.h"
45    
46    
47     /*
48     * ppc_cpu_family_init():
49     *
50     * Bogus function.
51     */
52     int ppc_cpu_family_init(struct cpu_family *fp)
53     {
54     return 0;
55     }
56    
57    
58     #else /* ENABLE_PPC */
59    
60    
61     #include "cpu.h"
62     #include "cpu_ppc.h"
63     #include "machine.h"
64     #include "memory.h"
65     #include "opcodes_ppc.h"
66     #include "symbol.h"
67    
68    
69     extern volatile int single_step;
70     extern int old_show_trace_tree;
71     extern int old_instruction_trace;
72     extern int old_quiet_mode;
73     extern int quiet_mode;
74    
75    
76     /*
77     * ppc_cpu_new():
78     *
79     * Create a new PPC cpu object.
80     */
81     struct cpu *ppc_cpu_new(struct memory *mem, struct machine *machine,
82     int cpu_id, char *cpu_type_name)
83     {
84     struct cpu *cpu;
85     int any_cache = 0;
86     int i, found;
87     struct ppc_cpu_type_def cpu_type_defs[] = PPC_CPU_TYPE_DEFS;
88    
89     /* Scan the cpu_type_defs list for this cpu type: */
90     i = 0;
91     found = -1;
92     while (i >= 0 && cpu_type_defs[i].name != NULL) {
93     if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
94     found = i;
95     break;
96     }
97     i++;
98     }
99     if (found == -1)
100     return NULL;
101    
102     cpu = malloc(sizeof(struct cpu));
103     if (cpu == NULL) {
104     fprintf(stderr, "out of memory\n");
105     exit(1);
106     }
107    
108     memset(cpu, 0, sizeof(struct cpu));
109     cpu->memory_rw = ppc_memory_rw;
110     cpu->cd.ppc.cpu_type = cpu_type_defs[found];
111     cpu->name = cpu->cd.ppc.cpu_type.name;
112     cpu->mem = mem;
113     cpu->machine = machine;
114     cpu->cpu_id = cpu_id;
115     cpu->byte_order = EMUL_BIG_ENDIAN;
116     cpu->cd.ppc.mode = MODE_PPC; /* TODO */
117     cpu->cd.ppc.of_emul_addr = 0xff000000; /* TODO */
118    
119     /* Current operating mode: */
120     cpu->cd.ppc.bits = cpu->cd.ppc.cpu_type.bits;
121     cpu->bootstrap_cpu_flag = 0;
122     cpu->running = 0;
123    
124     /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
125     if (cpu_id == 0) {
126     debug("%s", cpu->cd.ppc.cpu_type.name);
127    
128     if (cpu->cd.ppc.cpu_type.icache_shift != 0)
129     any_cache = 1;
130     if (cpu->cd.ppc.cpu_type.dcache_shift != 0)
131     any_cache = 1;
132     if (cpu->cd.ppc.cpu_type.l2cache_shift != 0)
133     any_cache = 1;
134    
135     if (any_cache) {
136     debug(" (I+D = %i+%i KB",
137     (int)(1 << (cpu->cd.ppc.cpu_type.icache_shift-10)),
138     (int)(1 << (cpu->cd.ppc.cpu_type.dcache_shift-10)));
139     if (cpu->cd.ppc.cpu_type.l2cache_shift != 0) {
140     debug(", L2 = %i KB",
141     (int)(1 << (cpu->cd.ppc.cpu_type.
142     l2cache_shift-10)));
143     }
144     debug(")");
145     }
146     }
147    
148     cpu->cd.ppc.pir = cpu_id;
149    
150     /* Some default stack pointer value. TODO: move this? */
151     cpu->cd.ppc.gpr[1] = machine->physical_ram_in_mb * 1048576 - 4096;
152    
153     return cpu;
154     }
155    
156    
157     /*
158     * ppc_cpu_list_available_types():
159     *
160     * Print a list of available PPC CPU types.
161     */
162     void ppc_cpu_list_available_types(void)
163     {
164     int i, j;
165     struct ppc_cpu_type_def tdefs[] = PPC_CPU_TYPE_DEFS;
166    
167     i = 0;
168     while (tdefs[i].name != NULL) {
169     debug("%s", tdefs[i].name);
170     for (j=10 - strlen(tdefs[i].name); j>0; j--)
171     debug(" ");
172     i++;
173     if ((i % 6) == 0 || tdefs[i].name == NULL)
174     debug("\n");
175     }
176     }
177    
178    
179     /*
180     * ppc_cpu_dumpinfo():
181     */
182     void ppc_cpu_dumpinfo(struct cpu *cpu)
183     {
184     struct ppc_cpu_type_def *ct = &cpu->cd.ppc.cpu_type;
185    
186     debug(" (%i-bit ", cpu->cd.ppc.bits);
187    
188     switch (cpu->cd.ppc.mode) {
189     case MODE_PPC:
190     debug("PPC");
191     break;
192     case MODE_POWER:
193     debug("POWER");
194     break;
195     default:
196     debug("_INTERNAL ERROR_");
197     }
198    
199     debug(", I+D = %i+%i KB",
200     (1 << ct->icache_shift) / 1024,
201     (1 << ct->dcache_shift) / 1024);
202    
203     if (ct->l2cache_shift) {
204     int kb = (1 << ct->l2cache_shift) / 1024;
205     debug(", L2 = %i %cB",
206     kb >= 1024? kb / 1024 : kb,
207     kb >= 1024? 'M' : 'K');
208     }
209    
210     debug(")\n");
211     }
212    
213    
214     /*
215     * reg_access_msr():
216     */
217     static void reg_access_msr(struct cpu *cpu, uint64_t *valuep, int writeflag)
218     {
219     if (valuep == NULL) {
220     fatal("reg_access_msr(): NULL\n");
221     return;
222     }
223    
224     if (writeflag)
225     cpu->cd.ppc.msr = *valuep;
226    
227     /* TODO: Is the little-endian bit writable? */
228    
229     cpu->cd.ppc.msr &= ~PPC_MSR_LE;
230     if (cpu->byte_order != EMUL_BIG_ENDIAN)
231     cpu->cd.ppc.msr |= PPC_MSR_LE;
232    
233     if (!writeflag)
234     *valuep = cpu->cd.ppc.msr;
235     }
236    
237    
238     /*
239     * ppc_cpu_register_dump():
240     *
241     * Dump cpu registers in a relatively readable format.
242     *
243     * gprs: set to non-zero to dump GPRs and some special-purpose registers.
244     * coprocs: set bit 0..3 to dump registers in coproc 0..3.
245     */
246     void ppc_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
247     {
248     char *symbol;
249     uint64_t offset, tmp;
250     int i, x = cpu->cpu_id;
251     int bits32 = cpu->cd.ppc.bits == 32;
252    
253     if (gprs) {
254     /* Special registers (pc, ...) first: */
255     symbol = get_symbol_name(&cpu->machine->symbol_context,
256     cpu->pc, &offset);
257    
258     debug("cpu%i: pc = 0x", x);
259     if (bits32)
260     debug("%08x", (int)cpu->pc);
261     else
262     debug("%016llx", (long long)cpu->pc);
263     debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
264    
265     debug("cpu%i: lr = 0x", x);
266     if (bits32)
267     debug("%08x", (int)cpu->cd.ppc.lr);
268     else
269     debug("%016llx", (long long)cpu->cd.ppc.lr);
270     debug(" cr = 0x%08x\n", (int)cpu->cd.ppc.cr);
271    
272     debug("cpu%i: ctr = 0x", x);
273     if (bits32)
274     debug("%08x", (int)cpu->cd.ppc.ctr);
275     else
276     debug("%016llx", (long long)cpu->cd.ppc.ctr);
277    
278     debug(" xer = 0x", x);
279     if (bits32)
280     debug("%08x\n", (int)cpu->cd.ppc.xer);
281     else
282     debug("%016llx\n", (long long)cpu->cd.ppc.xer);
283    
284     if (bits32) {
285     /* 32-bit: */
286     for (i=0; i<PPC_NGPRS; i++) {
287     if ((i % 4) == 0)
288     debug("cpu%i:", x);
289     debug(" r%02i = 0x%08x ", i,
290     (int)cpu->cd.ppc.gpr[i]);
291     if ((i % 4) == 3)
292     debug("\n");
293     }
294     } else {
295     /* 64-bit: */
296     for (i=0; i<PPC_NGPRS; i++) {
297     if ((i % 2) == 0)
298     debug("cpu%i:", x);
299     debug(" r%02i = 0x%016llx ", i,
300     (long long)cpu->cd.ppc.gpr[i]);
301     if ((i % 2) == 1)
302     debug("\n");
303     }
304     }
305    
306     /* Other special registers: */
307     reg_access_msr(cpu, &tmp, 0);
308     debug("cpu%i: msr = 0x%016llx ", x, (long long)tmp);
309     debug("tb = 0x%08x%08x\n",
310     (int)cpu->cd.ppc.tbu, (int)cpu->cd.ppc.tbl);
311     debug("cpu%i: dec = 0x%08x hdec = 0x%08x\n",
312     x, (int)cpu->cd.ppc.dec, (int)cpu->cd.ppc.hdec);
313     }
314    
315     if (coprocs) {
316     debug("cpu%i: fpscr = 0x%08x\n", x, (int)cpu->cd.ppc.fpscr);
317    
318     /* TODO: show floating-point values :-) */
319    
320     /* TODO: 32-bit fprs on 32-bit PPC cpus? */
321    
322     for (i=0; i<PPC_NFPRS; i++) {
323     if ((i % 2) == 0)
324     debug("cpu%i:", x);
325     debug(" f%02i = 0x%016llx ", i,
326     (long long)cpu->cd.ppc.fpr[i]);
327     if ((i % 2) == 1)
328     debug("\n");
329     }
330     }
331     }
332    
333    
334     /*
335     * ppc_cpu_register_match():
336     */
337     void ppc_cpu_register_match(struct machine *m, char *name,
338     int writeflag, uint64_t *valuep, int *match_register)
339     {
340     int cpunr = 0;
341    
342     /* CPU number: */
343    
344     /* TODO */
345    
346     /* Register name: */
347     if (strcasecmp(name, "pc") == 0) {
348     if (writeflag) {
349     m->cpus[cpunr]->pc = *valuep;
350     } else
351     *valuep = m->cpus[cpunr]->pc;
352     *match_register = 1;
353     } else if (strcasecmp(name, "msr") == 0) {
354     if (writeflag)
355     m->cpus[cpunr]->cd.ppc.msr = *valuep;
356     else
357     *valuep = m->cpus[cpunr]->cd.ppc.msr;
358     *match_register = 1;
359     } else if (strcasecmp(name, "lr") == 0) {
360     if (writeflag)
361     m->cpus[cpunr]->cd.ppc.lr = *valuep;
362     else
363     *valuep = m->cpus[cpunr]->cd.ppc.lr;
364     *match_register = 1;
365     } else if (strcasecmp(name, "cr") == 0) {
366     if (writeflag)
367     m->cpus[cpunr]->cd.ppc.cr = *valuep;
368     else
369     *valuep = m->cpus[cpunr]->cd.ppc.cr;
370     *match_register = 1;
371     } else if (strcasecmp(name, "dec") == 0) {
372     if (writeflag)
373     m->cpus[cpunr]->cd.ppc.dec = *valuep;
374     else
375     *valuep = m->cpus[cpunr]->cd.ppc.dec;
376     *match_register = 1;
377     } else if (strcasecmp(name, "hdec") == 0) {
378     if (writeflag)
379     m->cpus[cpunr]->cd.ppc.hdec = *valuep;
380     else
381     *valuep = m->cpus[cpunr]->cd.ppc.hdec;
382     *match_register = 1;
383     } else if (strcasecmp(name, "ctr") == 0) {
384     if (writeflag)
385     m->cpus[cpunr]->cd.ppc.ctr = *valuep;
386     else
387     *valuep = m->cpus[cpunr]->cd.ppc.ctr;
388     *match_register = 1;
389     } else if (name[0] == 'r' && isdigit((int)name[1])) {
390     int nr = atoi(name + 1);
391     if (nr >= 0 && nr < PPC_NGPRS) {
392     if (writeflag) {
393     m->cpus[cpunr]->cd.ppc.gpr[nr] = *valuep;
394     } else
395     *valuep = m->cpus[cpunr]->cd.ppc.gpr[nr];
396     *match_register = 1;
397     }
398     } else if (strcasecmp(name, "xer") == 0) {
399     if (writeflag)
400     m->cpus[cpunr]->cd.ppc.xer = *valuep;
401     else
402     *valuep = m->cpus[cpunr]->cd.ppc.xer;
403     *match_register = 1;
404     } else if (strcasecmp(name, "fpscr") == 0) {
405     if (writeflag)
406     m->cpus[cpunr]->cd.ppc.fpscr = *valuep;
407     else
408     *valuep = m->cpus[cpunr]->cd.ppc.fpscr;
409     *match_register = 1;
410     } else if (name[0] == 'f' && isdigit((int)name[1])) {
411     int nr = atoi(name + 1);
412     if (nr >= 0 && nr < PPC_NFPRS) {
413     if (writeflag) {
414     m->cpus[cpunr]->cd.ppc.fpr[nr] = *valuep;
415     } else
416     *valuep = m->cpus[cpunr]->cd.ppc.fpr[nr];
417     *match_register = 1;
418     }
419     }
420     }
421    
422    
423     /*
424     * ppc_cpu_disassemble_instr():
425     *
426     * Convert an instruction word into human readable format, for instruction
427     * tracing.
428     *
429     * If running is 1, cpu->pc should be the address of the instruction.
430     *
431     * If running is 0, things that depend on the runtime environment (eg.
432     * register contents) will not be shown, and addr will be used instead of
433     * cpu->pc for relative addresses.
434     */
435     int ppc_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
436     int running, uint64_t dumpaddr, int bintrans)
437     {
438     int hi6, xo, lev, rt, rs, ra, rb, imm, sh, me, rc, l_bit, oe_bit;
439     int spr, aa_bit, lk_bit, bf, bh, bi, bo, mb, nb, bt, ba, bb, fpreg;
440     int bfa;
441     uint64_t offset, addr;
442     uint32_t iword;
443     char *symbol, *mnem = "ERROR";
444     int power = cpu->cd.ppc.mode == MODE_POWER;
445    
446     if (running)
447     dumpaddr = cpu->pc;
448    
449     symbol = get_symbol_name(&cpu->machine->symbol_context,
450     dumpaddr, &offset);
451     if (symbol != NULL && offset==0)
452     debug("<%s>\n", symbol);
453    
454     if (cpu->machine->ncpus > 1 && running)
455     debug("cpu%i: ", cpu->cpu_id);
456    
457     if (cpu->cd.ppc.bits == 32)
458     debug("%08x", (int)dumpaddr);
459     else
460     debug("%016llx", (long long)dumpaddr);
461    
462     /* NOTE: Fixed to big-endian. */
463     iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)
464     + instr[3];
465    
466     debug(": %08x\t", iword);
467    
468     if (bintrans && !running) {
469     debug("(bintrans)");
470     goto disasm_ret;
471     }
472    
473     /*
474     * Decode the instruction:
475     */
476    
477     hi6 = iword >> 26;
478    
479     switch (hi6) {
480     case PPC_HI6_MULLI:
481     case PPC_HI6_SUBFIC:
482     rt = (iword >> 21) & 31;
483     ra = (iword >> 16) & 31;
484     imm = (int16_t)(iword & 0xffff);
485     switch (hi6) {
486     case PPC_HI6_MULLI:
487     mnem = power? "muli":"mulli";
488     break;
489     case PPC_HI6_SUBFIC:
490     mnem = power? "sfi":"subfic";
491     break;
492     }
493     debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
494     break;
495     case PPC_HI6_CMPLI:
496     case PPC_HI6_CMPI:
497     bf = (iword >> 23) & 7;
498     l_bit = (iword >> 21) & 1;
499     ra = (iword >> 16) & 31;
500     if (hi6 == PPC_HI6_CMPLI) {
501     imm = iword & 0xffff;
502     mnem = "cmpl";
503     } else {
504     imm = (int16_t)(iword & 0xffff);
505     mnem = "cmp";
506     }
507     debug("%s%si\t", mnem, l_bit? "d" : "w");
508     if (bf != 0)
509     debug("cr%i,", bf);
510     debug("r%i,%i", ra, imm);
511     break;
512     case PPC_HI6_ADDIC:
513     case PPC_HI6_ADDIC_DOT:
514     rt = (iword >> 21) & 31;
515     ra = (iword >> 16) & 31;
516     rc = hi6 == PPC_HI6_ADDIC_DOT;
517     imm = (int16_t)(iword & 0xffff);
518     mnem = power? "ai":"addic";
519     if (imm < 0 && !power) {
520     mnem = "subic";
521     imm = -imm;
522     }
523     debug("%s%s\tr%i,r%i,%i", mnem, rc?".":"", rt, ra, imm);
524     break;
525     case PPC_HI6_ADDI:
526     rt = (iword >> 21) & 31;
527     ra = (iword >> 16) & 31;
528     imm = (int16_t)(iword & 0xffff);
529     if (ra == 0)
530     debug("li\tr%i,%i", rt, imm);
531     else {
532     mnem = power? "cal":"addi";
533     if (imm < 0 && !power) {
534     mnem = "subi";
535     imm = -imm;
536     }
537     debug("%s\tr%i,r%i,%i", mnem, rt, ra, imm);
538     }
539     break;
540     case PPC_HI6_ADDIS:
541     rt = (iword >> 21) & 31;
542     ra = (iword >> 16) & 31;
543     imm = (int16_t)(iword & 0xffff);
544     if (ra == 0)
545     debug("lis\tr%i,%i", rt, imm);
546     else
547     debug("%s\tr%i,r%i,%i",
548     power? "cau":"addis", rt, ra, imm);
549     break;
550     case PPC_HI6_BC:
551     aa_bit = (iword & 2) >> 1;
552     lk_bit = iword & 1;
553     bo = (iword >> 21) & 31;
554     bi = (iword >> 16) & 31;
555     /* Sign-extend addr: */
556     addr = (int64_t)(int16_t)(iword & 0xfffc);
557     debug("bc");
558     if (lk_bit)
559     debug("l");
560     if (aa_bit)
561     debug("a");
562     else
563     addr += dumpaddr;
564     debug("\t%i,%i,", bo, bi);
565     if (cpu->cd.ppc.bits == 32)
566     addr &= 0xffffffff;
567     if (cpu->cd.ppc.bits == 32)
568     debug("0x%x", (int)addr);
569     else
570     debug("0x%llx", (long long)addr);
571     symbol = get_symbol_name(&cpu->machine->symbol_context,
572     addr, &offset);
573     if (symbol != NULL)
574     debug("\t<%s>", symbol);
575     break;
576     case PPC_HI6_SC:
577     lev = (iword >> 5) & 0x7f;
578     debug("sc");
579     if (lev != 0) {
580     debug("\t%i", lev);
581     if (lev > 1)
582     debug(" (WARNING! reserved value)");
583     }
584     break;
585     case PPC_HI6_B:
586     aa_bit = (iword & 2) >> 1;
587     lk_bit = iword & 1;
588     /* Sign-extend addr: */
589     addr = (int64_t)(int32_t)((iword & 0x03fffffc) << 6);
590     addr = (int64_t)addr >> 6;
591     debug("b");
592     if (lk_bit)
593     debug("l");
594     if (aa_bit)
595     debug("a");
596     else
597     addr += dumpaddr;
598     if (cpu->cd.ppc.bits == 32)
599     addr &= 0xffffffff;
600     if (cpu->cd.ppc.bits == 32)
601     debug("\t0x%x", (int)addr);
602     else
603     debug("\t0x%llx", (long long)addr);
604     symbol = get_symbol_name(&cpu->machine->symbol_context,
605     addr, &offset);
606     if (symbol != NULL)
607     debug("\t<%s>", symbol);
608     break;
609     case PPC_HI6_19:
610     xo = (iword >> 1) & 1023;
611     switch (xo) {
612     case PPC_19_MCRF:
613     bf = (iword >> 23) & 7;
614     bfa = (iword >> 18) & 7;
615     debug("mcrf\tcr%i,cr%i", bf, bfa);
616     break;
617     case PPC_19_BCLR:
618     case PPC_19_BCCTR:
619     bo = (iword >> 21) & 31;
620     bi = (iword >> 16) & 31;
621     bh = (iword >> 11) & 3;
622     lk_bit = iword & 1;
623     switch (xo) {
624     case PPC_19_BCLR:
625     mnem = power? "bcr" : "bclr"; break;
626     case PPC_19_BCCTR:
627     mnem = power? "bcc" : "bcctr"; break;
628     }
629     debug("%s%s%s\t%i,%i,%i", mnem, lk_bit? "l" : "",
630     bh? (bh==3? "+" : (bh==2? "-" : "?")) : "",
631     bo, bi, bh);
632     break;
633     case PPC_19_ISYNC:
634     debug("%s", power? "ics" : "isync");
635     break;
636     case PPC_19_CRAND:
637     case PPC_19_CRXOR:
638     case PPC_19_CROR:
639     case PPC_19_CRNAND:
640     case PPC_19_CRNOR:
641     case PPC_19_CRANDC:
642     case PPC_19_CREQV:
643     case PPC_19_CRORC:
644     bt = (iword >> 21) & 31;
645     ba = (iword >> 16) & 31;
646     bb = (iword >> 11) & 31;
647     switch (xo) {
648     case PPC_19_CRAND: mnem = "crand"; break;
649     case PPC_19_CRXOR: mnem = "crxor"; break;
650     case PPC_19_CROR: mnem = "cror"; break;
651     case PPC_19_CRNAND: mnem = "crnand"; break;
652     case PPC_19_CRNOR: mnem = "crnor"; break;
653     case PPC_19_CRANDC: mnem = "crandc"; break;
654     case PPC_19_CREQV: mnem = "creqv"; break;
655     case PPC_19_CRORC: mnem = "crorc"; break;
656     }
657     debug("%s\t%i,%i,%i", mnem, bt, ba, bb);
658     break;
659     default:
660     debug("unimplemented hi6_19, xo = 0x%x", xo);
661     }
662     break;
663     case PPC_HI6_RLWIMI:
664     case PPC_HI6_RLWINM:
665     rs = (iword >> 21) & 31;
666     ra = (iword >> 16) & 31;
667     sh = (iword >> 11) & 31;
668     mb = (iword >> 6) & 31;
669     me = (iword >> 1) & 31;
670     rc = iword & 1;
671     switch (hi6) {
672     case PPC_HI6_RLWIMI:
673     mnem = power? "rlimi" : "rlwimi"; break;
674     case PPC_HI6_RLWINM:
675     mnem = power? "rlinm" : "rlwinm"; break;
676     }
677     debug("%s%s\tr%i,r%i,%i,%i,%i",
678     mnem, rc?".":"", ra, rs, sh, mb, me);
679     break;
680     case PPC_HI6_ORI:
681     case PPC_HI6_ORIS:
682     case PPC_HI6_XORI:
683     case PPC_HI6_XORIS:
684     case PPC_HI6_ANDI_DOT:
685     case PPC_HI6_ANDIS_DOT:
686     rs = (iword >> 21) & 31;
687     ra = (iword >> 16) & 31;
688     imm = iword & 0xffff;
689     switch (hi6) {
690     case PPC_HI6_ORI:
691     mnem = power? "oril":"ori";
692     break;
693     case PPC_HI6_ORIS:
694     mnem = power? "oriu":"oris";
695     break;
696     case PPC_HI6_XORI:
697     mnem = power? "xoril":"xori";
698     break;
699     case PPC_HI6_XORIS:
700     mnem = power? "xoriu":"xoris";
701     break;
702     case PPC_HI6_ANDI_DOT:
703     mnem = power? "andil.":"andi.";
704     break;
705     case PPC_HI6_ANDIS_DOT:
706     mnem = power? "andiu.":"andis.";
707     break;
708     }
709     if (hi6 == PPC_HI6_ORI && rs == 0 && ra == 0 && imm == 0)
710     debug("nop");
711     else
712     debug("%s\tr%i,r%i,0x%04x", mnem, ra, rs, imm);
713     break;
714     case PPC_HI6_30:
715     xo = (iword >> 2) & 7;
716     switch (xo) {
717     case PPC_30_RLDICR:
718     rs = (iword >> 21) & 31;
719     ra = (iword >> 16) & 31;
720     sh = ((iword >> 11) & 31) | ((iword & 2) << 4);
721     me = ((iword >> 6) & 31) | (iword & 0x20);
722     rc = iword & 1;
723     debug("rldicr%s\tr%i,r%i,%i,%i",
724     rc?".":"", ra, rs, sh, me);
725     break;
726     default:
727     debug("unimplemented hi6_30, xo = 0x%x", xo);
728     }
729     break;
730     case PPC_HI6_31:
731     xo = (iword >> 1) & 1023;
732     switch (xo) {
733    
734     case PPC_31_CMP:
735     case PPC_31_CMPL:
736     bf = (iword >> 23) & 7;
737     l_bit = (iword >> 21) & 1;
738     ra = (iword >> 16) & 31;
739     rb = (iword >> 11) & 31;
740     if (xo == PPC_31_CMPL)
741     mnem = "cmpl";
742     else
743     mnem = "cmp";
744     debug("%s%s\t", mnem, l_bit? "d" : "w");
745     if (bf != 0)
746     debug("cr%i,", bf);
747     debug("r%i,r%i", ra, rb);
748     break;
749     case PPC_31_MFCR:
750     rt = (iword >> 21) & 31;
751     debug("mfcr\tr%i", rt);
752     break;
753     case PPC_31_DCBST:
754     case PPC_31_ICBI:
755     ra = (iword >> 16) & 31;
756     rb = (iword >> 11) & 31;
757     switch (xo) {
758     case PPC_31_DCBST: mnem = "dcbst"; break;
759     case PPC_31_ICBI: mnem = "icbi"; break;
760     }
761     debug("%s\tr%i,r%i", mnem, ra, rb);
762     break;
763     case PPC_31_MFMSR:
764     rt = (iword >> 21) & 31;
765     debug("mfmsr\tr%i", rt);
766     break;
767     case PPC_31_MTCRF:
768     rs = (iword >> 21) & 31;
769     mb = (iword >> 12) & 255; /* actually fxm, not mb */
770     debug("mtcrf\t%i,r%i", mb, rs);
771     break;
772     case PPC_31_MTMSR:
773     rs = (iword >> 21) & 31;
774     l_bit = (iword >> 16) & 1;
775     debug("mtmsr\tr%i", rs);
776     if (l_bit)
777     debug(",%i", l_bit);
778     break;
779     case PPC_31_LBZX:
780     case PPC_31_LBZUX:
781     case PPC_31_LHZX:
782     case PPC_31_LHZUX:
783     case PPC_31_LWZX:
784     case PPC_31_LWZUX:
785     case PPC_31_STBX:
786     case PPC_31_STBUX:
787     case PPC_31_STHX:
788     case PPC_31_STHUX:
789     case PPC_31_STWX:
790     case PPC_31_STWUX:
791     /* rs for stores, rt for loads, actually */
792     rs = (iword >> 21) & 31;
793     ra = (iword >> 16) & 31;
794     rb = (iword >> 11) & 31;
795     switch (xo) {
796     case PPC_31_LBZX: mnem = "lbzx"; break;
797     case PPC_31_LBZUX: mnem = "lbzux"; break;
798     case PPC_31_LHZX: mnem = "lhzx"; break;
799     case PPC_31_LHZUX: mnem = "lhzux"; break;
800     case PPC_31_LWZX:
801     mnem = power? "lx" : "lwzx";
802     break;
803     case PPC_31_LWZUX:
804     mnem = power? "lux" : "lwzux";
805     break;
806     case PPC_31_STBX: mnem = "stbx"; break;
807     case PPC_31_STBUX: mnem = "stbux"; break;
808     case PPC_31_STHX: mnem = "sthx"; break;
809     case PPC_31_STHUX: mnem = "sthux"; break;
810     case PPC_31_STWX:
811     mnem = power? "stx" : "stwx";
812     break;
813     case PPC_31_STWUX:
814     mnem = power? "stux" : "stwux";
815     break;
816     }
817     debug("%s\tr%i,r%i,r%i", mnem, rs, ra, rb);
818     if (running)
819     goto disasm_ret_nonewline;
820     break;
821     case PPC_31_NEG:
822     case PPC_31_NEGO:
823     rt = (iword >> 21) & 31;
824     ra = (iword >> 16) & 31;
825     oe_bit = (iword >> 10) & 1;
826     rc = iword & 1;
827     switch (xo) {
828     case PPC_31_NEG: mnem = "neg"; break;
829     case PPC_31_NEGO: mnem = "nego"; break;
830     }
831     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
832     break;
833     case PPC_31_ADDZE:
834     case PPC_31_ADDZEO:
835     rt = (iword >> 21) & 31;
836     ra = (iword >> 16) & 31;
837     oe_bit = (iword >> 10) & 1;
838     rc = iword & 1;
839     switch (xo) {
840     case PPC_31_ADDZE:
841     mnem = power? "aze" : "addze";
842     break;
843     case PPC_31_ADDZEO:
844     mnem = power? "azeo" : "addzeo";
845     break;
846     }
847     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", rt, ra);
848     break;
849     case PPC_31_MTSR:
850     /* Move to segment register (?) */
851     /* TODO */
852     debug("mtsr\tTODO");
853     break;
854     case PPC_31_MTSRIN:
855     case PPC_31_MFSRIN:
856     /* Move to/from segment register indirect */
857     rt = (iword >> 21) & 31;
858     rb = (iword >> 11) & 31;
859     switch (xo) {
860     case PPC_31_MTSRIN: mnem = "mtsrin"; break;
861     case PPC_31_MFSRIN: mnem = "mfsrin"; break;
862     }
863     debug("%s\tr%i,r%i", mnem, rt, rb);
864     break;
865     case PPC_31_ADDC:
866     case PPC_31_ADDCO:
867     case PPC_31_ADDE:
868     case PPC_31_ADDEO:
869     case PPC_31_ADD:
870     case PPC_31_ADDO:
871     case PPC_31_MULHW:
872     case PPC_31_MULHWU:
873     case PPC_31_MULLW:
874     case PPC_31_MULLWO:
875     case PPC_31_SUBF:
876     case PPC_31_SUBFO:
877     case PPC_31_SUBFC:
878     case PPC_31_SUBFCO:
879     case PPC_31_SUBFE:
880     case PPC_31_SUBFEO:
881     case PPC_31_SUBFZE:
882     case PPC_31_SUBFZEO:
883     rt = (iword >> 21) & 31;
884     ra = (iword >> 16) & 31;
885     rb = (iword >> 11) & 31;
886     oe_bit = (iword >> 10) & 1;
887     rc = iword & 1;
888     switch (xo) {
889     case PPC_31_ADDC:
890     mnem = power? "a" : "addc";
891     break;
892     case PPC_31_ADDCO:
893     mnem = power? "ao" : "addco";
894     break;
895     case PPC_31_ADDE:
896     mnem = power? "ae" : "adde";
897     break;
898     case PPC_31_ADDEO:
899     mnem = power? "aeo" : "addeo";
900     break;
901     case PPC_31_ADD:
902     mnem = power? "cax" : "add";
903     break;
904     case PPC_31_ADDO:
905     mnem = power? "caxo" : "addo";
906     break;
907     case PPC_31_MULHW: mnem = "mulhw"; break;
908     case PPC_31_MULHWU: mnem = "mulhwu"; break;
909     case PPC_31_MULLW:
910     mnem = power? "muls" : "mullw";
911     break;
912     case PPC_31_MULLWO:
913     mnem = power? "mulso" : "mullwo";
914     break;
915     case PPC_31_SUBF: mnem = "subf"; break;
916     case PPC_31_SUBFO: mnem = "subfo"; break;
917     case PPC_31_SUBFC:
918     mnem = power? "sf" : "subfc";
919     break;
920     case PPC_31_SUBFCO:
921     mnem = power? "sfo" : "subfco";
922     break;
923     case PPC_31_SUBFE:
924     mnem = power? "sfe" : "subfe";
925     break;
926     case PPC_31_SUBFEO:
927     mnem = power? "sfeo" : "subfeo";
928     break;
929     case PPC_31_SUBFZE:
930     mnem = power? "sfze" : "subfze";
931     break;
932     case PPC_31_SUBFZEO:
933     mnem = power? "sfzeo" : "subfzeo";
934     break;
935     }
936     debug("%s%s\tr%i,r%i,r%i", mnem, rc? "." : "",
937     rt, ra, rb);
938     break;
939     case PPC_31_MFSPR:
940     rt = (iword >> 21) & 31;
941     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
942     debug("mfspr\tr%i,spr%i", rt, spr);
943     break;
944     case PPC_31_TLBIE:
945     /* TODO: what is ra? The IBM online docs didn't say */
946     ra = 0;
947     rb = (iword >> 11) & 31;
948     if (power)
949     debug("tlbi\tr%i,r%i", ra, rb);
950     else
951     debug("tlbie\tr%i", rb);
952     break;
953     case PPC_31_TLBSYNC:
954     debug("tlbsync");
955     break;
956     case PPC_31_MFTB:
957     rt = (iword >> 21) & 31;
958     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
959     debug("mftb%s\tr%i", spr==268? "" :
960     (spr==269? "u" : "?"), rt);
961     break;
962     case PPC_31_CNTLZW:
963     rs = (iword >> 21) & 31;
964     ra = (iword >> 16) & 31;
965     rc = iword & 1;
966     mnem = power? "cntlz" : "cntlzw";
967     debug("%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
968     break;
969     case PPC_31_SLW:
970     case PPC_31_SRAW:
971     case PPC_31_SRW:
972     case PPC_31_AND:
973     case PPC_31_ANDC:
974     case PPC_31_NOR:
975     case PPC_31_OR:
976     case PPC_31_ORC:
977     case PPC_31_XOR:
978     case PPC_31_NAND:
979     rs = (iword >> 21) & 31;
980     ra = (iword >> 16) & 31;
981     rb = (iword >> 11) & 31;
982     rc = iword & 1;
983     if (rs == rb && xo == PPC_31_OR)
984     debug("mr%s\tr%i,r%i", rc? "." : "", ra, rs);
985     else {
986     switch (xo) {
987     case PPC_31_SLW: mnem =
988     power? "sl" : "slw"; break;
989     case PPC_31_SRAW: mnem =
990     power? "sra" : "sraw"; break;
991     case PPC_31_SRW: mnem =
992     power? "sr" : "srw"; break;
993     case PPC_31_AND: mnem = "and"; break;
994     case PPC_31_NAND: mnem = "nand"; break;
995     case PPC_31_ANDC: mnem = "andc"; break;
996     case PPC_31_NOR: mnem = "nor"; break;
997     case PPC_31_OR: mnem = "or"; break;
998     case PPC_31_ORC: mnem = "orc"; break;
999     case PPC_31_XOR: mnem = "xor"; break;
1000     }
1001     debug("%s%s\tr%i,r%i,r%i", mnem,
1002     rc? "." : "", ra, rs, rb);
1003     }
1004     break;
1005     case PPC_31_DCCCI:
1006     ra = (iword >> 16) & 31;
1007     rb = (iword >> 11) & 31;
1008     debug("dccci\tr%i,r%i", ra, rb);
1009     break;
1010     case PPC_31_ICCCI:
1011     ra = (iword >> 16) & 31;
1012     rb = (iword >> 11) & 31;
1013     debug("iccci\tr%i,r%i", ra, rb);
1014     break;
1015     case PPC_31_DIVW:
1016     case PPC_31_DIVWO:
1017     case PPC_31_DIVWU:
1018     case PPC_31_DIVWUO:
1019     rt = (iword >> 21) & 31;
1020     ra = (iword >> 16) & 31;
1021     rb = (iword >> 11) & 31;
1022     oe_bit = (iword >> 10) & 1;
1023     rc = iword & 1;
1024     switch (xo) {
1025     case PPC_31_DIVWU: mnem = "divwu"; break;
1026     case PPC_31_DIVWUO: mnem = "divwuo"; break;
1027     case PPC_31_DIVW: mnem = "divw"; break;
1028     case PPC_31_DIVWO: mnem = "divwo"; break;
1029     }
1030     debug("%s%s\tr%i,r%i,r%i", mnem, rc? "." : "",
1031     rt, ra, rb);
1032     break;
1033     case PPC_31_MTSPR:
1034     rs = (iword >> 21) & 31;
1035     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1036     debug("mtspr\tspr%i,r%i", spr, rs);
1037     break;
1038     case PPC_31_SYNC:
1039     debug("%s", power? "dcs" : "sync");
1040     break;
1041     case PPC_31_STSWI:
1042     rs = (iword >> 21) & 31;
1043     ra = (iword >> 16) & 31;
1044     nb = (iword >> 11) & 31;
1045     debug("%s\tr%i,r%i,%i", power? "stsi" : "stswi",
1046     rs, ra, nb);
1047     if (running)
1048     goto disasm_ret_nonewline;
1049     break;
1050     case PPC_31_SRAWI:
1051     rs = (iword >> 21) & 31;
1052     ra = (iword >> 16) & 31;
1053     sh = (iword >> 11) & 31;
1054     rc = iword & 1;
1055     mnem = power? "srai" : "srawi";
1056     debug("%s%s\tr%i,r%i,%i", mnem,
1057     rc? "." : "", ra, rs, sh);
1058     break;
1059     case PPC_31_EIEIO:
1060     debug("%s", power? "eieio?" : "eieio");
1061     break;
1062     case PPC_31_EXTSB:
1063     case PPC_31_EXTSH:
1064     case PPC_31_EXTSW:
1065     rs = (iword >> 21) & 31;
1066     ra = (iword >> 16) & 31;
1067     rc = iword & 1;
1068     switch (xo) {
1069     case PPC_31_EXTSB:
1070     mnem = power? "exts" : "extsb";
1071     break;
1072     case PPC_31_EXTSH:
1073     mnem = "extsh";
1074     break;
1075     case PPC_31_EXTSW:
1076     mnem = "extsw";
1077     break;
1078     }
1079     debug("%s%s\tr%i,r%i", mnem, rc? "." : "", ra, rs);
1080     break;
1081     default:
1082     debug("unimplemented hi6_31, xo = 0x%x", xo);
1083     }
1084     break;
1085     case PPC_HI6_LWZ:
1086     case PPC_HI6_LWZU:
1087     case PPC_HI6_LHZ:
1088     case PPC_HI6_LHZU:
1089     case PPC_HI6_LHA:
1090     case PPC_HI6_LHAU:
1091     case PPC_HI6_LBZ:
1092     case PPC_HI6_LBZU:
1093     case PPC_HI6_STW:
1094     case PPC_HI6_STWU:
1095     case PPC_HI6_STH:
1096     case PPC_HI6_STHU:
1097     case PPC_HI6_STB:
1098     case PPC_HI6_STBU:
1099     case PPC_HI6_STMW:
1100     case PPC_HI6_LFD:
1101     case PPC_HI6_STFD:
1102     /* NOTE: Loads use rt, not rs, but are otherwise similar
1103     to stores */
1104     rs = (iword >> 21) & 31;
1105     ra = (iword >> 16) & 31;
1106     imm = (int16_t)(iword & 0xffff);
1107     fpreg = 0;
1108     switch (hi6) {
1109     case PPC_HI6_LWZ: mnem = power? "l" : "lwz"; break;
1110     case PPC_HI6_LWZU: mnem = power? "lu" : "lwzu"; break;
1111     case PPC_HI6_LHZ: mnem = "lhz"; break;
1112     case PPC_HI6_LHZU: mnem = "lhzu"; break;
1113     case PPC_HI6_LHA: mnem = "lha"; break;
1114     case PPC_HI6_LHAU: mnem = "lhau"; break;
1115     case PPC_HI6_LBZ: mnem = "lbz"; break;
1116     case PPC_HI6_LBZU: mnem = "lbzu"; break;
1117     case PPC_HI6_STW: mnem = power? "st" : "stw"; break;
1118     case PPC_HI6_STWU: mnem = power? "stu" : "stwu"; break;
1119     case PPC_HI6_STH: mnem = "sth"; break;
1120     case PPC_HI6_STHU: mnem = "sthu"; break;
1121     case PPC_HI6_STB: mnem = "stb"; break;
1122     case PPC_HI6_STBU: mnem = "stbu"; break;
1123     case PPC_HI6_LMW: mnem = power? "lm" : "lmw"; break;
1124     case PPC_HI6_STMW: mnem = power? "stm" : "stmw"; break;
1125     case PPC_HI6_LFD: fpreg = 1; mnem = "lfd"; break;
1126     case PPC_HI6_STFD: fpreg = 1; mnem = "stfd"; break;
1127     }
1128     debug("%s\t", mnem);
1129     if (fpreg)
1130     debug("f");
1131     else
1132     debug("r");
1133     debug("%i,%i(r%i)", rs, imm, ra);
1134     if (running)
1135     goto disasm_ret_nonewline;
1136     break;
1137     default:
1138     /* TODO */
1139     debug("unimplemented hi6 = 0x%02x", hi6);
1140     }
1141    
1142     disasm_ret:
1143     debug("\n");
1144     disasm_ret_nonewline:
1145     return sizeof(iword);
1146     }
1147    
1148    
1149     /*
1150     * show_trace():
1151     *
1152     * Show trace tree. This function should be called every time
1153     * a function is called. cpu->cd.ppc.trace_tree_depth is increased here
1154     * and should not be increased by the caller.
1155     *
1156     * Note: This function should not be called if show_trace_tree == 0.
1157     */
1158     static void show_trace(struct cpu *cpu)
1159     {
1160     uint64_t offset, addr = cpu->pc;
1161     int x, n_args_to_print;
1162     char strbuf[60];
1163     char *symbol;
1164    
1165     cpu->cd.ppc.trace_tree_depth ++;
1166    
1167     if (cpu->machine->ncpus > 1)
1168     debug("cpu%i:", cpu->cpu_id);
1169    
1170     symbol = get_symbol_name(&cpu->machine->symbol_context, addr, &offset);
1171    
1172     for (x=0; x<cpu->cd.ppc.trace_tree_depth; x++)
1173     debug(" ");
1174    
1175     /* debug("<%s>\n", symbol!=NULL? symbol : "no symbol"); */
1176    
1177     if (symbol != NULL)
1178     debug("<%s(", symbol);
1179     else {
1180     debug("<0x");
1181     if (cpu->cd.ppc.bits == 32)
1182     debug("%08x", (int)addr);
1183     else
1184     debug("%016llx", (long long)addr);
1185     debug("(");
1186     }
1187    
1188     /*
1189     * TODO: The number of arguments and the symbol type of each
1190     * argument should be taken from the symbol table, in some way.
1191     */
1192     n_args_to_print = 5;
1193    
1194     for (x=0; x<n_args_to_print; x++) {
1195     int64_t d = cpu->cd.ppc.gpr[x + 3];
1196    
1197     if (d > -256 && d < 256)
1198     debug("%i", (int)d);
1199     else if (memory_points_to_string(cpu, cpu->mem, d, 1)) {
1200     debug("\"%s\"", memory_conv_to_string(cpu,
1201     cpu->mem, d, strbuf, sizeof(strbuf)));
1202     if (strlen(strbuf) >= sizeof(strbuf)-1)
1203     debug("..");
1204     } else {
1205     if (cpu->cd.ppc.bits == 32)
1206     debug("0x%x", (int)d);
1207     else
1208     debug("0x%llx", (long long)d);
1209     }
1210    
1211     if (x < n_args_to_print - 1)
1212     debug(",");
1213    
1214     if (x == n_args_to_print - 1)
1215     break;
1216     }
1217    
1218     if (n_args_to_print > 9)
1219     debug("..");
1220    
1221     debug(")>\n");
1222     }
1223    
1224    
1225     /*
1226     * update_cr0():
1227     *
1228     * Sets the top 4 bits of the CR register.
1229     */
1230     static void update_cr0(struct cpu *cpu, uint64_t value)
1231     {
1232     int c;
1233    
1234     if (cpu->cd.ppc.bits == 64) {
1235     if ((int64_t)value < 0)
1236     c = 8;
1237     else if ((int64_t)value > 0)
1238     c = 4;
1239     else
1240     c = 2;
1241     } else {
1242     if ((int32_t)value < 0)
1243     c = 8;
1244     else if ((int32_t)value > 0)
1245     c = 4;
1246     else
1247     c = 2;
1248     }
1249    
1250     /* SO bit, copied from XER: */
1251     c |= ((cpu->cd.ppc.xer >> 31) & 1);
1252    
1253     cpu->cd.ppc.cr &= ~((uint32_t)0xf << 28);
1254     cpu->cd.ppc.cr |= ((uint32_t)c << 28);
1255     }
1256    
1257    
1258     /*
1259     * ppc_cpu_run_instr():
1260     *
1261     * Execute one instruction on a specific CPU.
1262     *
1263     * Return value is the number of instructions executed during this call,
1264     * 0 if no instruction was executed.
1265     */
1266     int ppc_cpu_run_instr(struct emul *emul, struct cpu *cpu)
1267     {
1268     uint32_t iword;
1269     unsigned char buf[4];
1270     unsigned char tmp_data[8];
1271     size_t tmp_data_len;
1272     char *mnem = NULL;
1273     int r, hi6, rt, rs, ra, rb, xo, lev, sh, me, rc, imm, l_bit, oe_bit;
1274     int c, i, spr, aa_bit, bo, bi, bh, lk_bit, bf, ctr_ok, cond_ok;
1275     int update, load, mb, nb, bt, ba, bb, fpreg, arithflag, old_ca, bfa;
1276     uint64_t tmp=0, tmp2, addr;
1277     uint64_t cached_pc;
1278    
1279     cached_pc = cpu->cd.ppc.pc_last = cpu->pc & ~3;
1280    
1281     /* Check PC against breakpoints: */
1282     if (!single_step)
1283     for (i=0; i<cpu->machine->n_breakpoints; i++)
1284     if (cached_pc == cpu->machine->breakpoint_addr[i]) {
1285     fatal("Breakpoint reached, pc=0x");
1286     if (cpu->cd.ppc.bits == 32)
1287     fatal("%08x", (int)cached_pc);
1288     else
1289     fatal("%016llx", (long long)cached_pc);
1290     fatal("\n");
1291     single_step = 1;
1292     return 0;
1293     }
1294    
1295     /* Update the Time Base and Decrementer: */
1296     if ((++ cpu->cd.ppc.tbl) == 0)
1297     cpu->cd.ppc.tbu ++;
1298    
1299     cpu->cd.ppc.dec --;
1300     /* TODO: dec interrupt! */
1301    
1302     /* TODO: hdec for POWER4+ */
1303    
1304     /* ROM emulation: (TODO: non-OF-emuls) */
1305     if (cpu->pc == cpu->cd.ppc.of_emul_addr &&
1306     cpu->machine->prom_emulation) {
1307     int res = of_emul(cpu);
1308     if (res) {
1309     cpu->pc = cpu->cd.ppc.lr;
1310     }
1311     return 100;
1312     }
1313    
1314     r = cpu->memory_rw(cpu, cpu->mem, cached_pc, &buf[0], sizeof(buf),
1315     MEM_READ, CACHE_INSTRUCTION | PHYSICAL);
1316     if (!r)
1317     return 0;
1318    
1319     iword = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3];
1320    
1321     if (cpu->machine->instruction_trace)
1322     ppc_cpu_disassemble_instr(cpu, buf, 1, 0, 0);
1323    
1324     cpu->pc += sizeof(iword);
1325     cached_pc += sizeof(iword);
1326    
1327     hi6 = iword >> 26;
1328    
1329     switch (hi6) {
1330    
1331     case PPC_HI6_MULLI:
1332     rt = (iword >> 21) & 31;
1333     ra = (iword >> 16) & 31;
1334     imm = (int16_t)(iword & 0xffff);
1335     cpu->cd.ppc.gpr[rt] = (int64_t)cpu->cd.ppc.gpr[ra]
1336     * (int64_t)imm;
1337     break;
1338    
1339     case PPC_HI6_SUBFIC:
1340     rt = (iword >> 21) & 31;
1341     ra = (iword >> 16) & 31;
1342     imm = (int16_t)(iword & 0xffff);
1343     cpu->cd.ppc.xer &= ~PPC_XER_CA;
1344     if (cpu->cd.ppc.bits == 32) {
1345     tmp = (~cpu->cd.ppc.gpr[ra]) & 0xffffffff;
1346     cpu->cd.ppc.gpr[rt] = tmp + imm + 1;
1347     /* TODO: is this CA correct? */
1348     /* printf("subfic: tmp = %016llx\n", (long long)tmp);
1349     printf("subfic: rt = %016llx\n\n",
1350     (long long)cpu->cd.ppc.gpr[rt]); */
1351     if ((tmp >> 32) != (cpu->cd.ppc.gpr[rt] >> 32))
1352     cpu->cd.ppc.xer |= PPC_XER_CA;
1353     /* High 32 bits are probably undefined in
1354     32-bit mode (I hope) */
1355     } else {
1356     /*
1357     * Ugly, but I can't figure out a way right now how
1358     * to get the carry bit out of a 64-bit addition,
1359     * without access to more-than-64-bit operations in C.
1360     */
1361     tmp = ~cpu->cd.ppc.gpr[ra];
1362     tmp2 = (tmp >> 32); /* High 32 bits */
1363     tmp &= 0xffffffff; /* Low 32 bits */
1364    
1365     tmp += imm + 1;
1366     if ((tmp >> 32) == 0) {
1367     /* No change to upper 32 bits */
1368     } else if ((tmp >> 32) == 1) {
1369     /* Positive change: */
1370     tmp2 ++;
1371     } else {
1372     /* Negative change: */
1373     tmp2 --;
1374     }
1375    
1376     tmp &= 0xffffffff;
1377    
1378     /* TODO: is this CA calculation correct? */
1379     if ((tmp2 >> 32) != 0)
1380     cpu->cd.ppc.xer |= PPC_XER_CA;
1381    
1382     cpu->cd.ppc.gpr[rt] = (tmp2 << 32) + tmp;
1383     }
1384     break;
1385    
1386     case PPC_HI6_CMPLI:
1387     case PPC_HI6_CMPI:
1388     bf = (iword >> 23) & 7;
1389     l_bit = (iword >> 21) & 1;
1390     ra = (iword >> 16) & 31;
1391     if (hi6 == PPC_HI6_CMPLI)
1392     imm = iword & 0xffff;
1393     else
1394     imm = (int16_t)(iword & 0xffff);
1395     tmp = cpu->cd.ppc.gpr[ra];
1396    
1397     if (hi6 == PPC_HI6_CMPI) {
1398     if (!l_bit)
1399     tmp = (int64_t)(int32_t)tmp;
1400     if ((int64_t)tmp < (int64_t)imm)
1401     c = 8;
1402     else if ((int64_t)tmp > (int64_t)imm)
1403     c = 4;
1404     else
1405     c = 2;
1406     } else {
1407     if (!l_bit)
1408     tmp &= 0xffffffff;
1409     if ((uint64_t)tmp < (uint64_t)imm)
1410     c = 8;
1411     else if ((uint64_t)tmp > (uint64_t)imm)
1412     c = 4;
1413     else
1414     c = 2;
1415     }
1416    
1417     /* SO bit, copied from XER: */
1418     c |= ((cpu->cd.ppc.xer >> 31) & 1);
1419    
1420     cpu->cd.ppc.cr &= ~(0xf << (28 - 4*bf));
1421     cpu->cd.ppc.cr |= (c << (28 - 4*bf));
1422     break;
1423    
1424     case PPC_HI6_ADDIC:
1425     case PPC_HI6_ADDIC_DOT:
1426     rt = (iword >> 21) & 31;
1427     ra = (iword >> 16) & 31;
1428     rc = hi6 == PPC_HI6_ADDIC_DOT;
1429     imm = (int16_t)(iword & 0xffff);
1430     /* NOTE: Addic doesn't clear CA! */
1431     if (cpu->cd.ppc.bits == 32) {
1432     tmp = cpu->cd.ppc.gpr[ra] & 0xffffffff;
1433     cpu->cd.ppc.gpr[rt] = tmp + (uint32_t)imm;
1434     /* TODO: is this CA correct? */
1435     /* printf("addic: tmp = %016llx\n", (long long)tmp);
1436     printf("addic: rt = %016llx\n\n",
1437     (long long)cpu->cd.ppc.gpr[rt]); */
1438     if ((tmp >> 32) != (cpu->cd.ppc.gpr[rt] >> 32))
1439     cpu->cd.ppc.xer |= PPC_XER_CA;
1440     /* High 32 bits are probably undefined in
1441     32-bit mode (I hope) */
1442     } else {
1443     /* See comment about ugliness regarding SUBFIC */
1444     tmp = cpu->cd.ppc.gpr[ra];
1445     tmp2 = (tmp >> 32); /* High 32 bits */
1446     tmp &= 0xffffffff; /* Low 32 bits */
1447    
1448     tmp += (int64_t)imm;
1449     if ((tmp >> 32) == 0) {
1450     /* No change to upper 32 bits */
1451     } else if ((tmp >> 32) == 1) {
1452     /* Positive change: */
1453     tmp2 ++;
1454     } else {
1455     /* Negative change: */
1456     tmp2 --;
1457     }
1458    
1459     tmp &= 0xffffffff;
1460    
1461     /* TODO: is this CA calculation correct? */
1462     if ((tmp2 >> 32) != 0)
1463     cpu->cd.ppc.xer |= PPC_XER_CA;
1464    
1465     cpu->cd.ppc.gpr[rt] = (tmp2 << 32) + tmp;
1466     }
1467     if (rc)
1468     update_cr0(cpu, cpu->cd.ppc.gpr[rt]);
1469     break;
1470    
1471     case PPC_HI6_ADDI:
1472     case PPC_HI6_ADDIS:
1473     rt = (iword >> 21) & 31;
1474     ra = (iword >> 16) & 31;
1475     if (hi6 == PPC_HI6_ADDI)
1476     imm = (int16_t)(iword & 0xffff);
1477     else
1478     imm = (int32_t)((iword & 0xffff) << 16);
1479     if (ra == 0)
1480     tmp = 0;
1481     else
1482     tmp = cpu->cd.ppc.gpr[ra];
1483     cpu->cd.ppc.gpr[rt] = tmp + imm;
1484     break;
1485    
1486     case PPC_HI6_BC:
1487     aa_bit = (iword >> 1) & 1;
1488     lk_bit = iword & 1;
1489     bo = (iword >> 21) & 31;
1490     bi = (iword >> 16) & 31;
1491     /* Sign-extend addr: */
1492     addr = (int64_t)(int16_t)(iword & 0xfffc);
1493    
1494     if (!aa_bit)
1495     addr += cpu->cd.ppc.pc_last;
1496    
1497     if (cpu->cd.ppc.bits == 32)
1498     addr &= 0xffffffff;
1499    
1500     if (!(bo & 4))
1501     cpu->cd.ppc.ctr --;
1502     ctr_ok = (bo >> 2) & 1;
1503     tmp = cpu->cd.ppc.ctr;
1504     if (cpu->cd.ppc.bits == 32)
1505     tmp &= 0xffffffff;
1506     ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
1507    
1508     cond_ok = (bo >> 4) & 1;
1509     cond_ok |= ( ((bo >> 3) & 1) ==
1510     ((cpu->cd.ppc.cr >> (31-bi)) & 1) );
1511    
1512     if (lk_bit)
1513     cpu->cd.ppc.lr = cpu->pc;
1514     if (ctr_ok && cond_ok)
1515     cpu->pc = addr & ~3;
1516     if (lk_bit && cpu->machine->show_trace_tree)
1517     show_trace(cpu);
1518     break;
1519    
1520     case PPC_HI6_SC:
1521     lev = (iword >> 5) & 0x7f;
1522     if (cpu->machine->userland_emul != NULL) {
1523     useremul_syscall(cpu, lev);
1524     } else {
1525     fatal("[ PPC: pc = 0x%016llx, sc not yet "
1526     "implemented ]\n", (long long)cached_pc);
1527     cpu->running = 0;
1528     return 0;
1529     }
1530     break;
1531    
1532     case PPC_HI6_B:
1533     aa_bit = (iword & 2) >> 1;
1534     lk_bit = iword & 1;
1535     /* Sign-extend addr: */
1536     addr = (int64_t)(int32_t)((iword & 0x03fffffc) << 6);
1537     addr = (int64_t)addr >> 6;
1538    
1539     if (!aa_bit)
1540     addr += cpu->cd.ppc.pc_last;
1541    
1542     if (cpu->cd.ppc.bits == 32)
1543     addr &= 0xffffffff;
1544    
1545     if (lk_bit)
1546     cpu->cd.ppc.lr = cpu->pc;
1547    
1548     cpu->pc = addr;
1549    
1550     if (lk_bit && cpu->machine->show_trace_tree)
1551     show_trace(cpu);
1552     break;
1553    
1554     case PPC_HI6_19:
1555     xo = (iword >> 1) & 1023;
1556     switch (xo) {
1557    
1558     case PPC_19_MCRF:
1559     bf = (iword >> 23) & 7;
1560     bfa = (iword >> 18) & 7;
1561     tmp = cpu->cd.ppc.cr >> (28 - bfa*4);
1562     tmp &= 0xf;
1563     cpu->cd.ppc.cr &= ~(0xf << (28 - bf*4));
1564     cpu->cd.ppc.cr |= (tmp << (28 - bf*4));
1565     break;
1566    
1567     case PPC_19_BCLR:
1568     case PPC_19_BCCTR:
1569     bo = (iword >> 21) & 31;
1570     bi = (iword >> 16) & 31;
1571     bh = (iword >> 11) & 3;
1572     lk_bit = iword & 1;
1573     if (xo == PPC_19_BCLR) {
1574     addr = cpu->cd.ppc.lr;
1575     if (!(bo & 4))
1576     cpu->cd.ppc.ctr --;
1577     ctr_ok = (bo >> 2) & 1;
1578     tmp = cpu->cd.ppc.ctr;
1579     if (cpu->cd.ppc.bits == 32)
1580     tmp &= 0xffffffff;
1581     ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
1582     if (!quiet_mode && !lk_bit &&
1583     cpu->machine->show_trace_tree) {
1584     cpu->cd.ppc.trace_tree_depth --;
1585     /* TODO: show return value? */
1586     }
1587     } else {
1588     addr = cpu->cd.ppc.ctr;
1589     ctr_ok = 1;
1590     }
1591     cond_ok = (bo >> 4) & 1;
1592     cond_ok |= ( ((bo >> 3) & 1) ==
1593     ((cpu->cd.ppc.cr >> (31-bi)) & 1) );
1594     if (lk_bit)
1595     cpu->cd.ppc.lr = cpu->pc;
1596     if (ctr_ok && cond_ok) {
1597     cpu->pc = addr & ~3;
1598     if (cpu->cd.ppc.bits == 32)
1599     cpu->pc &= 0xffffffff;
1600     }
1601     if (lk_bit && cpu->machine->show_trace_tree)
1602     show_trace(cpu);
1603     break;
1604    
1605     case PPC_19_ISYNC:
1606     /* TODO: actually sync */
1607     break;
1608    
1609     case PPC_19_CRAND:
1610     case PPC_19_CRXOR:
1611     case PPC_19_CROR:
1612     case PPC_19_CRNAND:
1613     case PPC_19_CRNOR:
1614     case PPC_19_CRANDC:
1615     case PPC_19_CREQV:
1616     case PPC_19_CRORC:
1617     bt = (iword >> 21) & 31;
1618     ba = (iword >> 16) & 31;
1619     bb = (iword >> 11) & 31;
1620     ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
1621     bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
1622     cpu->cd.ppc.cr &= ~(1 << (31-bt));
1623     switch (xo) {
1624     case PPC_19_CRXOR:
1625     if (ba ^ bb)
1626     cpu->cd.ppc.cr |= (1 << (31-bt));
1627     break;
1628     case PPC_19_CROR:
1629     if (ba | bb)
1630     cpu->cd.ppc.cr |= (1 << (31-bt));
1631     break;
1632     default:
1633     fatal("[ TODO: crXXX, xo = %i, "
1634     "pc = 0x%016llx ]\n",
1635     xo, (long long) (cpu->cd.ppc.pc_last));
1636     cpu->running = 0;
1637     return 0;
1638     }
1639     break;
1640    
1641     default:
1642     fatal("[ unimplemented PPC hi6_19, xo = 0x%04x, "
1643     "pc = 0x%016llx ]\n",
1644     xo, (long long) (cpu->cd.ppc.pc_last));
1645     cpu->running = 0;
1646     return 0;
1647     }
1648     break;
1649    
1650     case PPC_HI6_RLWIMI:
1651     case PPC_HI6_RLWINM:
1652     rs = (iword >> 21) & 31;
1653     ra = (iword >> 16) & 31;
1654     sh = (iword >> 11) & 31;
1655     mb = (iword >> 6) & 31;
1656     me = (iword >> 1) & 31;
1657     rc = iword & 1;
1658     tmp = cpu->cd.ppc.gpr[rs];
1659     /* TODO: Fix this, its performance is awful: */
1660     while (sh-- != 0) {
1661     int b = (tmp >> 31) & 1;
1662     tmp = (tmp << 1) | b;
1663     }
1664    
1665     switch (hi6) {
1666     case PPC_HI6_RLWIMI:
1667     for (;;) {
1668     uint64_t mask;
1669     mask = (uint64_t)1 << (31-mb);
1670     cpu->cd.ppc.gpr[ra] &= ~mask;
1671     cpu->cd.ppc.gpr[ra] |= (tmp & mask);
1672     if (mb == me)
1673     break;
1674     mb ++;
1675     if (mb == 32)
1676     mb = 0;
1677     }
1678     break;
1679     case PPC_HI6_RLWINM:
1680     cpu->cd.ppc.gpr[ra] = 0;
1681     for (;;) {
1682     uint64_t mask;
1683     mask = (uint64_t)1 << (31-mb);
1684     cpu->cd.ppc.gpr[ra] |= (tmp & mask);
1685     if (mb == me)
1686     break;
1687     mb ++;
1688     if (mb == 32)
1689     mb = 0;
1690     }
1691     break;
1692     }
1693     if (rc)
1694     update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
1695     break;
1696    
1697     case PPC_HI6_ORI:
1698     case PPC_HI6_ORIS:
1699     rs = (iword >> 21) & 31;
1700     ra = (iword >> 16) & 31;
1701     if (hi6 == PPC_HI6_ORI)
1702     imm = (iword & 0xffff);
1703     else
1704     imm = (iword & 0xffff) << 16;
1705     tmp = cpu->cd.ppc.gpr[rs];
1706     cpu->cd.ppc.gpr[ra] = tmp | (uint32_t)imm;
1707     break;
1708    
1709     case PPC_HI6_XORI:
1710     case PPC_HI6_XORIS:
1711     rs = (iword >> 21) & 31;
1712     ra = (iword >> 16) & 31;
1713     if (hi6 == PPC_HI6_XORI)
1714     imm = (iword & 0xffff);
1715     else
1716     imm = (iword & 0xffff) << 16;
1717     tmp = cpu->cd.ppc.gpr[rs];
1718     cpu->cd.ppc.gpr[ra] = tmp ^ (uint32_t)imm;
1719     break;
1720    
1721     case PPC_HI6_ANDI_DOT:
1722     case PPC_HI6_ANDIS_DOT:
1723     rs = (iword >> 21) & 31;
1724     ra = (iword >> 16) & 31;
1725     if (hi6 == PPC_HI6_ANDI_DOT)
1726     imm = (iword & 0xffff);
1727     else
1728     imm = (iword & 0xffff) << 16;
1729     tmp = cpu->cd.ppc.gpr[rs];
1730     cpu->cd.ppc.gpr[ra] = tmp & (uint32_t)imm;
1731     update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
1732     break;
1733    
1734     case PPC_HI6_30:
1735     xo = (iword >> 2) & 7;
1736     switch (xo) {
1737     case PPC_30_RLDICR:
1738     if (cpu->cd.ppc.bits == 32) {
1739     /* TODO: Illegal instruction. */
1740     break;
1741     }
1742     rs = (iword >> 21) & 31;
1743     ra = (iword >> 16) & 31;
1744     sh = ((iword >> 11) & 31) | ((iword & 2) << 4);
1745     me = ((iword >> 6) & 31) | (iword & 0x20);
1746     rc = iword & 1;
1747     tmp = cpu->cd.ppc.gpr[rs];
1748     /* TODO: Fix this, its performance is awful: */
1749     while (sh-- != 0) {
1750     int b = (tmp >> 63) & 1;
1751     tmp = (tmp << 1) | b;
1752     }
1753     while (me++ < 63)
1754     tmp &= ~((uint64_t)1 << (63-me));
1755     cpu->cd.ppc.gpr[ra] = tmp;
1756     if (rc)
1757     update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
1758     break;
1759     default:
1760     fatal("[ unimplemented PPC hi6_30, xo = 0x%04x, "
1761     "pc = 0x%016llx ]\n",
1762     xo, (long long) (cpu->cd.ppc.pc_last));
1763     cpu->running = 0;
1764     return 0;
1765     }
1766     break;
1767    
1768     case PPC_HI6_31:
1769     xo = (iword >> 1) & 1023;
1770     switch (xo) {
1771    
1772     case PPC_31_CMPL:
1773     case PPC_31_CMP:
1774     bf = (iword >> 23) & 7;
1775     l_bit = (iword >> 21) & 1;
1776     ra = (iword >> 16) & 31;
1777     rb = (iword >> 11) & 31;
1778    
1779     tmp = cpu->cd.ppc.gpr[ra];
1780     tmp2 = cpu->cd.ppc.gpr[rb];
1781    
1782     if (hi6 == PPC_31_CMP) {
1783     if (!l_bit) {
1784     tmp = (int64_t)(int32_t)tmp;
1785     tmp2 = (int64_t)(int32_t)tmp2;
1786     }
1787     if ((int64_t)tmp < (int64_t)tmp2)
1788     c = 8;
1789     else if ((int64_t)tmp > (int64_t)tmp2)
1790     c = 4;
1791     else
1792     c = 2;
1793     } else {
1794     if (!l_bit) {
1795     tmp &= 0xffffffff;
1796     tmp2 &= 0xffffffff;
1797     }
1798     if ((uint64_t)tmp < (uint64_t)tmp2)
1799     c = 8;
1800     else if ((uint64_t)tmp > (uint64_t)tmp2)
1801     c = 4;
1802     else
1803     c = 2;
1804     }
1805    
1806     /* SO bit, copied from XER: */
1807     c |= ((cpu->cd.ppc.xer >> 31) & 1);
1808    
1809     cpu->cd.ppc.cr &= ~(0xf << (28 - 4*bf));
1810     cpu->cd.ppc.cr |= (c << (28 - 4*bf));
1811     break;
1812    
1813     case PPC_31_MFCR:
1814     rt = (iword >> 21) & 31;
1815     cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.cr;
1816     break;
1817    
1818     case PPC_31_DCBST:
1819     case PPC_31_ICBI:
1820     ra = (iword >> 16) & 31;
1821     rb = (iword >> 11) & 31;
1822     switch (xo) {
1823     case PPC_31_DCBST: mnem = "dcbst"; break;
1824     case PPC_31_ICBI: mnem = "icbi"; break;
1825     }
1826     /* debug("[ %s r%i,r%i: TODO ]\n", mnem, ra, rb); */
1827     break;
1828    
1829     case PPC_31_MFMSR:
1830     rt = (iword >> 21) & 31;
1831     /* TODO: check pr */
1832     reg_access_msr(cpu, &cpu->cd.ppc.gpr[rt], 0);
1833     break;
1834    
1835     case PPC_31_MTCRF:
1836     rs = (iword >> 21) & 31;
1837     mb = (iword >> 12) & 255; /* actually fxm, not mb */
1838     tmp = 0;
1839     for (i=0; i<8; i++, mb <<= 1, tmp <<= 4)
1840     if (mb & 128)
1841     tmp |= 0xf;
1842     cpu->cd.ppc.cr &= ~tmp;
1843     cpu->cd.ppc.cr |= (cpu->cd.ppc.gpr[rs] & tmp);
1844     break;
1845    
1846     case PPC_31_MTMSR:
1847     rs = (iword >> 21) & 31;
1848     l_bit = (iword >> 16) & 1;
1849     /* TODO: the l_bit */
1850     reg_access_msr(cpu, &cpu->cd.ppc.gpr[rs], 1);
1851     break;
1852    
1853     case PPC_31_LBZX:
1854     case PPC_31_LBZUX:
1855     case PPC_31_LHZX:
1856     case PPC_31_LHZUX:
1857     case PPC_31_LWZX:
1858     case PPC_31_LWZUX:
1859     case PPC_31_STBX:
1860     case PPC_31_STBUX:
1861     case PPC_31_STHX:
1862     case PPC_31_STHUX:
1863     case PPC_31_STWX:
1864     case PPC_31_STWUX:
1865     rs = (iword >> 21) & 31;
1866     ra = (iword >> 16) & 31;
1867     rb = (iword >> 11) & 31;
1868     update = 0;
1869     switch (xo) {
1870     case PPC_31_LBZUX:
1871     case PPC_31_LHZUX:
1872     case PPC_31_LWZUX:
1873     case PPC_31_STBUX:
1874     case PPC_31_STHUX:
1875     case PPC_31_STWUX:
1876     update = 1;
1877     }
1878     if (ra == 0)
1879     addr = 0;
1880     else
1881     addr = cpu->cd.ppc.gpr[ra];
1882     addr += cpu->cd.ppc.gpr[rb];
1883     load = 0;
1884     switch (xo) {
1885     case PPC_31_LBZX:
1886     case PPC_31_LBZUX:
1887     case PPC_31_LHZX:
1888     case PPC_31_LHZUX:
1889     case PPC_31_LWZX:
1890     case PPC_31_LWZUX:
1891     load = 1;
1892     }
1893    
1894     if (cpu->machine->instruction_trace) {
1895     if (cpu->cd.ppc.bits == 32)
1896     debug("\t[0x%08llx", (long long)addr);
1897     else
1898     debug("\t[0x%016llx", (long long)addr);
1899     }
1900    
1901     tmp_data_len = 4;
1902     switch (xo) {
1903     case PPC_31_LBZX:
1904     case PPC_31_LBZUX:
1905     case PPC_31_STBX:
1906     case PPC_31_STBUX:
1907     tmp_data_len = 1;
1908     break;
1909     case PPC_31_LHZX:
1910     case PPC_31_LHZUX:
1911     case PPC_31_STHX:
1912     case PPC_31_STHUX:
1913     tmp_data_len = 2;
1914     break;
1915     }
1916    
1917     tmp = 0;
1918    
1919     if (load) {
1920     r = cpu->memory_rw(cpu, cpu->mem, addr,
1921     tmp_data, tmp_data_len, MEM_READ,
1922     CACHE_DATA);
1923     if (r == MEMORY_ACCESS_OK) {
1924     if (cpu->byte_order ==
1925     EMUL_BIG_ENDIAN) {
1926     for (i=0; i<tmp_data_len; i++) {
1927     tmp <<= 8;
1928     tmp += tmp_data[i];
1929     }
1930     } else {
1931     for (i=0; i<tmp_data_len; i++) {
1932     tmp <<= 8;
1933     tmp += tmp_data[
1934     tmp_data_len - 1
1935     - i];
1936     }
1937     }
1938     cpu->cd.ppc.gpr[rs] = tmp;
1939     }
1940     } else {
1941     tmp = cpu->cd.ppc.gpr[rs];
1942     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
1943     for (i=0; i<tmp_data_len; i++)
1944     tmp_data[tmp_data_len-1-i] =
1945     tmp >> (8*i);
1946     } else {
1947     for (i=0; i<tmp_data_len; i++)
1948     tmp_data[i] = tmp >> (8*i);
1949     }
1950    
1951     r = cpu->memory_rw(cpu, cpu->mem, addr,
1952     tmp_data, tmp_data_len, MEM_WRITE,
1953     CACHE_DATA);
1954     }
1955    
1956     if (cpu->machine->instruction_trace) {
1957     if (r == MEMORY_ACCESS_OK) {
1958     switch (tmp_data_len) {
1959     case 1: debug(", data = 0x%02x]\n",
1960     (int)tmp);
1961     break;
1962     case 2: debug(", data = 0x%04x]\n",
1963     (int)tmp);
1964     break;
1965     case 4: debug(", data = 0x%08x]\n",
1966     (int)tmp);
1967     break;
1968     default:debug(", data = 0x%016llx]\n",
1969     (long long)tmp);
1970     }
1971     } else
1972     debug(", FAILED]\n");
1973     }
1974    
1975     if (r != MEMORY_ACCESS_OK) {
1976     /* TODO: exception? */
1977     return 0;
1978     }
1979    
1980     if (update && ra != 0)
1981     cpu->cd.ppc.gpr[ra] = addr;
1982     break;
1983    
1984     case PPC_31_NEG:
1985     case PPC_31_NEGO:
1986     rt = (iword >> 21) & 31;
1987     ra = (iword >> 16) & 31;
1988     oe_bit = (iword >> 10) & 1;
1989     rc = iword & 1;
1990     if (oe_bit) {
1991     fatal("[ neg: PPC oe not yet implemeted ]\n");
1992     cpu->running = 0;
1993     return 0;
1994     }
1995     cpu->cd.ppc.gpr[rt] = ~cpu->cd.ppc.gpr[ra] + 1;
1996     if (rc)
1997     update_cr0(cpu, cpu->cd.ppc.gpr[rt]);
1998     break;
1999    
2000     case PPC_31_ADDZE:
2001     case PPC_31_ADDZEO:
2002     rt = (iword >> 21) & 31;
2003     ra = (iword >> 16) & 31;
2004     oe_bit = (iword >> 10) & 1;
2005     rc = iword & 1;
2006     if (oe_bit) {
2007     fatal("[ addz: PPC oe not yet implemeted ]\n");
2008     cpu->running = 0;
2009     return 0;
2010     }
2011     old_ca = cpu->cd.ppc.xer & PPC_XER_CA;
2012     cpu->cd.ppc.xer &= PPC_XER_CA;
2013     if (cpu->cd.ppc.bits == 32) {
2014     tmp = (uint32_t)cpu->cd.ppc.gpr[ra];
2015     tmp2 = tmp;
2016     /* printf("addze: tmp2 = %016llx\n",
2017     (long long)tmp2); */
2018     if (old_ca)
2019     tmp ++;
2020     /* printf("addze: tmp = %016llx\n\n",
2021     (long long)tmp); */
2022     /* TODO: is this CA correct? */
2023     if ((tmp >> 32) != (tmp2 >> 32))
2024     cpu->cd.ppc.xer |= PPC_XER_CA;
2025     /* High 32 bits are probably undefined
2026     in 32-bit mode (I hope) */
2027     cpu->cd.ppc.gpr[rt] = tmp;
2028     } else {
2029     fatal("ADDZE 64-bit, TODO\n");
2030     }
2031     if (rc)
2032     update_cr0(cpu, cpu->cd.ppc.gpr[rt]);
2033     break;
2034    
2035     case PPC_31_MTSR:
2036     /* Move to segment register (?) */
2037     /* TODO */
2038     break;
2039    
2040     case PPC_31_MFSRIN:
2041     case PPC_31_MTSRIN:
2042     /* mfsrin: Move to segment register indirect (?) */
2043     /* mtsrin: Move to segment register indirect (?) */
2044     rt = (iword >> 21) & 31;
2045     rb = (iword >> 11) & 31;
2046    
2047     /* TODO */
2048    
2049     if (xo == PPC_31_MFSRIN)
2050     cpu->cd.ppc.gpr[rt] = 0;
2051     break;
2052    
2053     case PPC_31_ADDC:
2054     case PPC_31_ADDCO:
2055     case PPC_31_ADDE:
2056     case PPC_31_ADDEO:
2057     case PPC_31_ADD:
2058     case PPC_31_ADDO:
2059     case PPC_31_MULHW:
2060     case PPC_31_MULHWU:
2061     case PPC_31_MULLW:
2062     case PPC_31_MULLWO:
2063     case PPC_31_SUBFE:
2064     case PPC_31_SUBFEO:
2065     case PPC_31_SUBFZE:
2066     case PPC_31_SUBFZEO:
2067     case PPC_31_SUBFC:
2068     case PPC_31_SUBFCO:
2069     case PPC_31_SUBF:
2070     case PPC_31_SUBFO:
2071     rt = (iword >> 21) & 31;
2072     ra = (iword >> 16) & 31;
2073     rb = (iword >> 11) & 31;
2074     oe_bit = (iword >> 10) & 1;
2075     rc = iword & 1;
2076     if (oe_bit) {
2077     fatal("[ add: PPC oe not yet implemeted ]\n");
2078     cpu->running = 0;
2079     return 0;
2080     }
2081     switch (xo) {
2082     case PPC_31_ADD:
2083     case PPC_31_ADDO:
2084     cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.gpr[ra] +
2085     cpu->cd.ppc.gpr[rb];
2086     break;
2087     case PPC_31_ADDC:
2088     case PPC_31_ADDCO:
2089     case PPC_31_ADDE:
2090     case PPC_31_ADDEO:
2091     old_ca = cpu->cd.ppc.xer & PPC_XER_CA;
2092     cpu->cd.ppc.xer &= PPC_XER_CA;
2093     if (cpu->cd.ppc.bits == 32) {
2094     tmp = (uint32_t)cpu->cd.ppc.gpr[ra];
2095     tmp2 = tmp;
2096     /* printf("adde: tmp2 = %016llx\n",
2097     (long long)tmp2); */
2098     tmp += (uint32_t)cpu->cd.ppc.gpr[rb];
2099     if ((xo == PPC_31_ADDE ||
2100     xo == PPC_31_ADDEO) && old_ca)
2101     tmp ++;
2102     /* printf("adde: tmp = %016llx\n\n",
2103     (long long)tmp); */
2104     /* TODO: is this CA correct? */
2105     if ((tmp >> 32) != (tmp2 >> 32))
2106     cpu->cd.ppc.xer |= PPC_XER_CA;
2107     /* High 32 bits are probably undefined
2108     in 32-bit mode (I hope) */
2109     cpu->cd.ppc.gpr[rt] = tmp;
2110     } else {
2111     fatal("ADDE 64-bit, TODO\n");
2112     }
2113     break;
2114     case PPC_31_MULHW:
2115     cpu->cd.ppc.gpr[rt] = (int64_t) (
2116     (int64_t)(int32_t)cpu->cd.ppc.gpr[ra] *
2117     (int64_t)(int32_t)cpu->cd.ppc.gpr[rb]);
2118     cpu->cd.ppc.gpr[rt] >>= 32;
2119     break;
2120     case PPC_31_MULHWU:
2121     cpu->cd.ppc.gpr[rt] = (uint64_t) (
2122     (uint64_t)(uint32_t)cpu->cd.ppc.gpr[ra] *
2123     (uint64_t)(uint32_t)cpu->cd.ppc.gpr[rb]);
2124     cpu->cd.ppc.gpr[rt] >>= 32;
2125     break;
2126     case PPC_31_MULLW:
2127     case PPC_31_MULLWO:
2128     cpu->cd.ppc.gpr[rt] = (int64_t) (
2129     (int32_t)cpu->cd.ppc.gpr[ra] *
2130     (int32_t)cpu->cd.ppc.gpr[rb]);
2131     break;
2132     case PPC_31_SUBF:
2133     case PPC_31_SUBFO:
2134     cpu->cd.ppc.gpr[rt] = ~cpu->cd.ppc.gpr[ra] +
2135     cpu->cd.ppc.gpr[rb] + 1;
2136     break;
2137     case PPC_31_SUBFC:
2138     case PPC_31_SUBFCO:
2139     case PPC_31_SUBFE:
2140     case PPC_31_SUBFEO:
2141     case PPC_31_SUBFZE:
2142     case PPC_31_SUBFZEO:
2143     old_ca = cpu->cd.ppc.xer & PPC_XER_CA;
2144     if (xo == PPC_31_SUBFC || xo == PPC_31_SUBFCO)
2145     old_ca = 1;
2146     cpu->cd.ppc.xer &= PPC_XER_CA;
2147     if (cpu->cd.ppc.bits == 32) {
2148     tmp = (~cpu->cd.ppc.gpr[ra])
2149     & 0xffffffff;
2150     tmp2 = tmp;
2151     if (xo != PPC_31_SUBFZE &&
2152     xo != PPC_31_SUBFZEO)
2153     tmp += (cpu->cd.ppc.gpr[rb] &
2154     0xffffffff);
2155     if (old_ca)
2156     tmp ++;
2157     /* printf("subfe: tmp2 = %016llx\n",
2158     (long long)tmp2);
2159     printf("subfe: tmp = %016llx\n\n",
2160     (long long)tmp); */
2161     /* TODO: is this CA correct? */
2162     if ((tmp >> 32) != (tmp2 >> 32))
2163     cpu->cd.ppc.xer |= PPC_XER_CA;
2164     /* High 32 bits are probably undefined
2165     in 32-bit mode (I hope) */
2166     cpu->cd.ppc.gpr[rt] = tmp;
2167     } else {
2168     fatal("SUBFE 64-bit, TODO\n");
2169     }
2170     break;
2171     }
2172     if (rc)
2173     update_cr0(cpu, cpu->cd.ppc.gpr[rt]);
2174     break;
2175    
2176     case PPC_31_MFSPR:
2177     case PPC_31_MFTB:
2178     rt = (iword >> 21) & 31;
2179     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
2180     switch (spr) {
2181     case 1: cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.xer;
2182     break;
2183     case 8: cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.lr;
2184     break;
2185     case 9: cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.ctr;
2186     break;
2187     case 22:/* TODO: check pr */
2188     cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.dec;
2189     break;
2190     case 259: /* NOTE: no pr check */
2191     cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.sprg3;
2192     break;
2193     case 268: /* MFTB, NOTE: no pr check */
2194     cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.tbl;
2195     break;
2196     case 269: /* MFTBU, NOTE: no pr check */
2197     cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.tbu;
2198     break;
2199     case 272:
2200     /* TODO: check pr */
2201     cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.sprg0;
2202     break;
2203     case 273:
2204     /* TODO: check pr */
2205     cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.sprg1;
2206     break;
2207     case 274:
2208     /* TODO: check pr */
2209     cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.sprg2;
2210     break;
2211     case 275:
2212     /* TODO: check pr */
2213     cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.sprg3;
2214     break;
2215     case 287:
2216     /* TODO: check pr */
2217     cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.pvr;
2218     break;
2219     case 310:/* TODO: check pr */
2220     cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.hdec;
2221     break;
2222     case 1023:
2223     /* TODO: check pr */
2224     cpu->cd.ppc.gpr[rt] = cpu->cd.ppc.pir;
2225     break;
2226     default:
2227     fatal("[ unimplemented PPC spr 0x%04x, "
2228     "pc = 0x%016llx ]\n",
2229     spr, (long long) (cpu->cd.ppc.pc_last));
2230     /* cpu->running = 0;
2231     return 0; */
2232     break;
2233     }
2234    
2235     /* TODO: is this correct? */
2236     if (cpu->cd.ppc.bits == 32)
2237     cpu->cd.ppc.gpr[rt] &= 0xffffffff;
2238     break;
2239    
2240     case PPC_31_CNTLZW:
2241     rs = (iword >> 21) & 31;
2242     ra = (iword >> 16) & 31;
2243     rc = iword & 1;
2244     cpu->cd.ppc.gpr[ra] = 0;
2245     for (i=0; i<32; i++) {
2246     if (cpu->cd.ppc.gpr[rs] &
2247     ((uint64_t)1 << (31-i)))
2248     break;
2249     cpu->cd.ppc.gpr[ra] ++;
2250     }
2251     if (rc)
2252     update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
2253     break;
2254    
2255     case PPC_31_SLW:
2256     case PPC_31_SRAW:
2257     case PPC_31_SRW:
2258     case PPC_31_AND:
2259     case PPC_31_ANDC:
2260     case PPC_31_NOR:
2261     case PPC_31_OR:
2262     case PPC_31_ORC:
2263     case PPC_31_XOR:
2264     case PPC_31_NAND:
2265     rs = (iword >> 21) & 31;
2266     ra = (iword >> 16) & 31;
2267     rb = (iword >> 11) & 31;
2268     rc = iword & 1;
2269     switch (xo) {
2270     case PPC_31_SLW:
2271     sh = cpu->cd.ppc.gpr[rb] & 0x3f;
2272     cpu->cd.ppc.gpr[ra] = cpu->cd.ppc.gpr[rs];
2273     while (sh-- > 0)
2274     cpu->cd.ppc.gpr[ra] <<= 1;
2275     cpu->cd.ppc.gpr[ra] &= 0xffffffff;
2276     break;
2277     case PPC_31_SRAW:
2278     tmp = cpu->cd.ppc.gpr[rs] & 0xffffffff;
2279     cpu->cd.ppc.xer &= ~PPC_XER_CA;
2280     i = 0;
2281     sh = cpu->cd.ppc.gpr[rb] & 0x3f;
2282     if (tmp & 0x80000000)
2283     i = 1;
2284     while (sh-- > 0) {
2285     if (tmp & 1)
2286     i++;
2287     tmp >>= 1;
2288     if (tmp & 0x40000000)
2289     tmp |= 0x80000000;
2290     }
2291     cpu->cd.ppc.gpr[ra] = (int64_t)(int32_t)tmp;
2292     /* Set the CA bit if rs contained a negative
2293     number to begin with, and any 1-bits were
2294     shifted out: */
2295     if (i > 1)
2296     cpu->cd.ppc.xer |= PPC_XER_CA;
2297     break;
2298     case PPC_31_SRW:
2299     sh = cpu->cd.ppc.gpr[rb] & 0x3f;
2300     cpu->cd.ppc.gpr[ra] = cpu->cd.ppc.gpr[rs]
2301     & 0xffffffff;
2302     while (sh-- > 0)
2303     cpu->cd.ppc.gpr[ra] >>= 1;
2304     break;
2305     case PPC_31_AND:
2306     cpu->cd.ppc.gpr[ra] = cpu->cd.ppc.gpr[rs] &
2307     cpu->cd.ppc.gpr[rb];
2308     break;
2309     case PPC_31_ANDC:
2310     cpu->cd.ppc.gpr[ra] = cpu->cd.ppc.gpr[rs] &
2311     (~cpu->cd.ppc.gpr[rb]);
2312     break;
2313     case PPC_31_NOR:
2314     cpu->cd.ppc.gpr[ra] = ~(cpu->cd.ppc.gpr[rs] |
2315     cpu->cd.ppc.gpr[rb]);
2316     break;
2317     case PPC_31_OR:
2318     cpu->cd.ppc.gpr[ra] = cpu->cd.ppc.gpr[rs] |
2319     cpu->cd.ppc.gpr[rb];
2320     break;
2321     case PPC_31_ORC:
2322     cpu->cd.ppc.gpr[ra] = cpu->cd.ppc.gpr[rs] |
2323     (~cpu->cd.ppc.gpr[rb]);
2324     break;
2325     case PPC_31_XOR:
2326     cpu->cd.ppc.gpr[ra] = cpu->cd.ppc.gpr[rs] ^
2327     cpu->cd.ppc.gpr[rb];
2328     break;
2329     case PPC_31_NAND:
2330     cpu->cd.ppc.gpr[ra] = ~(cpu->cd.ppc.gpr[rs]
2331     & cpu->cd.ppc.gpr[rb]);
2332     break;
2333     }
2334     if (rc)
2335     update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
2336     break;
2337    
2338     case PPC_31_TLBIE:
2339     rb = (iword >> 11) & 31;
2340     /* TODO */
2341     break;
2342    
2343     case PPC_31_TLBSYNC:
2344     /* Only on 603 and 604 (?) */
2345    
2346     /* TODO */
2347     break;
2348    
2349     case PPC_31_DCCCI:
2350     case PPC_31_ICCCI:
2351     /* Supervisor IBM 4xx Data Cache Congruence Class
2352     Invalidate, see www.xilinx.com/publications/
2353     xcellonline/partners/xc_pdf/xc_ibm_pwrpc42.pdf
2354     or similar */
2355     /* ICCCI is probably Instruction... blah blah */
2356     /* TODO */
2357     break;
2358    
2359     case PPC_31_DIVWU:
2360     case PPC_31_DIVWUO:
2361     case PPC_31_DIVW:
2362     case PPC_31_DIVWO:
2363     rt = (iword >> 21) & 31;
2364     ra = (iword >> 16) & 31;
2365     rb = (iword >> 11) & 31;
2366     oe_bit = (iword >> 10) & 1;
2367     rc = iword & 1;
2368     switch (xo) {
2369     case PPC_31_DIVWU:
2370     case PPC_31_DIVWUO:
2371     tmp = cpu->cd.ppc.gpr[ra] & 0xffffffff;
2372     tmp2 = cpu->cd.ppc.gpr[rb] & 0xffffffff;
2373     if (tmp2 == 0) {
2374     /* Undefined: */
2375     tmp = 0;
2376     } else {
2377     tmp = tmp / tmp2;
2378     }
2379     cpu->cd.ppc.gpr[rt] = (int64_t)(int32_t)tmp;
2380     break;
2381     case PPC_31_DIVW:
2382     case PPC_31_DIVWO:
2383     tmp = (int64_t)(int32_t)cpu->cd.ppc.gpr[ra];
2384     tmp2 = (int64_t)(int32_t)cpu->cd.ppc.gpr[rb];
2385     if (tmp2 == 0) {
2386     /* Undefined: */
2387     tmp = 0;
2388     } else {
2389     tmp = (int64_t)tmp / (int64_t)tmp2;
2390     }
2391     cpu->cd.ppc.gpr[rt] = (int64_t)(int32_t)tmp;
2392     break;
2393     }
2394     if (rc)
2395     update_cr0(cpu, cpu->cd.ppc.gpr[rt]);
2396     if (oe_bit) {
2397     fatal("[ divwu: PPC oe not yet implemeted ]\n");
2398     cpu->running = 0;
2399     return 0;
2400     }
2401     break;
2402    
2403     case PPC_31_MTSPR:
2404     rs = (iword >> 21) & 31;
2405     spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
2406     switch (spr) {
2407     case 1: cpu->cd.ppc.xer = cpu->cd.ppc.gpr[rs];
2408     break;
2409     case 8: cpu->cd.ppc.lr = cpu->cd.ppc.gpr[rs];
2410     break;
2411     case 9: cpu->cd.ppc.ctr = cpu->cd.ppc.gpr[rs];
2412     break;
2413     case 22: /* TODO: check pr */
2414     cpu->cd.ppc.dec = cpu->cd.ppc.gpr[rs];
2415     break;
2416     case 272:
2417     /* TODO: check hypv */
2418     cpu->cd.ppc.sprg0 = cpu->cd.ppc.gpr[rs];
2419     break;
2420     case 273:
2421     /* TODO: check pr */
2422     cpu->cd.ppc.sprg1 = cpu->cd.ppc.gpr[rs];
2423     break;
2424     case 274:
2425     /* TODO: check pr */
2426     cpu->cd.ppc.sprg2 = cpu->cd.ppc.gpr[rs];
2427     break;
2428     case 275:
2429     /* TODO: check pr */
2430     cpu->cd.ppc.sprg3 = cpu->cd.ppc.gpr[rs];
2431     break;
2432     case 284:
2433     /* TODO: check pr */
2434     cpu->cd.ppc.tbl = cpu->cd.ppc.gpr[rs];
2435     break;
2436     case 285:
2437     /* TODO: check pr */
2438     cpu->cd.ppc.tbu = cpu->cd.ppc.gpr[rs];
2439     break;
2440     case 287:
2441     fatal("[ PPC: attempt to write to PVR ]\n");
2442     break;
2443     case 310: /* TODO: check hypv */
2444     cpu->cd.ppc.hdec = cpu->cd.ppc.gpr[rs];
2445     break;
2446     case 1023:
2447     /* TODO: check pr */
2448     cpu->cd.ppc.pir = cpu->cd.ppc.gpr[rs];
2449     break;
2450     default:
2451     fatal("[ unimplemented PPC spr 0x%04x, "
2452     "pc = 0x%016llx ]\n",
2453     spr, (long long) (cpu->cd.ppc.pc_last));
2454     /* cpu->running = 0;
2455     return 0; */
2456     break;
2457     }
2458     break;
2459    
2460     case PPC_31_SYNC:
2461     /* TODO: actually sync */
2462     break;
2463    
2464     case PPC_31_STSWI:
2465     rs = (iword >> 21) & 31;
2466     ra = (iword >> 16) & 31;
2467     nb = (iword >> 11) & 31;
2468     if (nb == 0)
2469     nb = 32;
2470     if (ra == 0)
2471     addr = 0;
2472     else
2473     addr = cpu->cd.ppc.gpr[ra];
2474    
2475     if (cpu->machine->instruction_trace) {
2476     if (cpu->cd.ppc.bits == 32)
2477     debug("\t[0x%08llx", (long long)addr);
2478     else
2479     debug("\t[0x%016llx", (long long)addr);
2480     }
2481    
2482     i = 24;
2483     r = 0; /* There can be multiple errors */
2484     while (nb > 0) {
2485     tmp_data[0] = cpu->cd.ppc.gpr[rs] >> i;
2486     if (cpu->memory_rw(cpu, cpu->mem, addr,
2487     tmp_data, 1, MEM_WRITE, CACHE_DATA)
2488     != MEMORY_ACCESS_OK)
2489     r++;
2490     nb--; addr++; i-=8;
2491     if (i < 0) {
2492     i = 24;
2493     rs = (rs + 1) % 32;
2494     }
2495     }
2496    
2497     if (cpu->machine->instruction_trace) {
2498     if (r == 0)
2499     debug(", ...]\n");
2500     else
2501     debug(", FAILED]\n");
2502     }
2503    
2504     if (r > 0) {
2505     /* TODO: exception */
2506     return 0;
2507     }
2508     break;
2509    
2510     case PPC_31_SRAWI:
2511     rs = (iword >> 21) & 31;
2512     ra = (iword >> 16) & 31;
2513     sh = (iword >> 11) & 31;
2514     rc = iword & 1;
2515     tmp = cpu->cd.ppc.gpr[rs] & 0xffffffff;
2516     cpu->cd.ppc.xer &= ~PPC_XER_CA;
2517     i = 0;
2518     if (tmp & 0x80000000)
2519     i = 1;
2520     while (sh-- > 0) {
2521     if (tmp & 1)
2522     i++;
2523     tmp >>= 1;
2524     if (tmp & 0x40000000)
2525     tmp |= 0x80000000;
2526     }
2527     cpu->cd.ppc.gpr[ra] = (int64_t)(int32_t)tmp;
2528     /* Set the CA bit if rs contained a negative
2529     number to begin with, and any 1-bits were
2530     shifted out: */
2531     if (i > 1)
2532     cpu->cd.ppc.xer |= PPC_XER_CA;
2533     if (rc)
2534     update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
2535     break;
2536    
2537     case PPC_31_EIEIO:
2538     /* TODO: actually eieio */
2539     break;
2540    
2541     case PPC_31_EXTSB:
2542     case PPC_31_EXTSH:
2543     case PPC_31_EXTSW:
2544     rs = (iword >> 21) & 31;
2545     ra = (iword >> 16) & 31;
2546     rc = iword & 1;
2547     switch (xo) {
2548     case PPC_31_EXTSB:
2549     cpu->cd.ppc.gpr[ra] = (int64_t)
2550     (int8_t)cpu->cd.ppc.gpr[rs];
2551     break;
2552     case PPC_31_EXTSH:
2553     cpu->cd.ppc.gpr[ra] = (int64_t)
2554     (int16_t)cpu->cd.ppc.gpr[rs];
2555     break;
2556     case PPC_31_EXTSW:
2557     cpu->cd.ppc.gpr[ra] = (int64_t)
2558     (int32_t)cpu->cd.ppc.gpr[rs];
2559     break;
2560     }
2561     if (rc)
2562     update_cr0(cpu, cpu->cd.ppc.gpr[ra]);
2563     break;
2564    
2565     default:
2566     fatal("[ unimplemented PPC hi6_31, xo = 0x%04x, "
2567     "pc = 0x%016llx ]\n",
2568     xo, (long long) (cpu->cd.ppc.pc_last));
2569     cpu->running = 0;
2570     return 0;
2571     }
2572     break;
2573    
2574     case PPC_HI6_LWZ:
2575     case PPC_HI6_LWZU:
2576     case PPC_HI6_LHZ:
2577     case PPC_HI6_LHZU:
2578     case PPC_HI6_LHA:
2579     case PPC_HI6_LHAU:
2580     case PPC_HI6_LBZ:
2581     case PPC_HI6_LBZU:
2582     case PPC_HI6_STW:
2583     case PPC_HI6_STWU:
2584     case PPC_HI6_STH:
2585     case PPC_HI6_STHU:
2586     case PPC_HI6_STB:
2587     case PPC_HI6_STBU:
2588     case PPC_HI6_LFD:
2589     case PPC_HI6_STFD:
2590     /* NOTE: Loads use rt, not rs, but are otherwise similar
2591     to stores. This code uses rs for both. */
2592     rs = (iword >> 21) & 31;
2593     ra = (iword >> 16) & 31;
2594     imm = (int16_t)(iword & 0xffff);
2595    
2596     fpreg = 0; load = 1; update = 0; tmp_data_len = 4;
2597     arithflag = 0;
2598    
2599     switch (hi6) {
2600     case PPC_HI6_LWZU:
2601     case PPC_HI6_LHZU:
2602     case PPC_HI6_LHAU:
2603     case PPC_HI6_LBZU:
2604     case PPC_HI6_STBU:
2605     case PPC_HI6_STHU:
2606     case PPC_HI6_STWU:
2607     update = 1;
2608     }
2609    
2610     switch (hi6) {
2611     case PPC_HI6_STW:
2612     case PPC_HI6_STWU:
2613     case PPC_HI6_STH:
2614     case PPC_HI6_STHU:
2615     case PPC_HI6_STB:
2616     case PPC_HI6_STBU:
2617     case PPC_HI6_STFD:
2618     load = 0;
2619     }
2620    
2621     switch (hi6) {
2622     case PPC_HI6_LFD:
2623     case PPC_HI6_STFD:
2624     tmp_data_len = 8;
2625     break;
2626     case PPC_HI6_LBZ:
2627     case PPC_HI6_LBZU:
2628     case PPC_HI6_STB:
2629     case PPC_HI6_STBU:
2630     tmp_data_len = 1;
2631     break;
2632     case PPC_HI6_LHZ:
2633     case PPC_HI6_LHZU:
2634     case PPC_HI6_LHA:
2635     case PPC_HI6_LHAU:
2636     case PPC_HI6_STH:
2637     case PPC_HI6_STHU:
2638     tmp_data_len = 2;
2639     break;
2640     }
2641    
2642     switch (hi6) {
2643     case PPC_HI6_LFD:
2644     case PPC_HI6_STFD:
2645     fpreg = 1;
2646     }
2647    
2648     switch (hi6) {
2649     case PPC_HI6_LHA:
2650     case PPC_HI6_LHAU:
2651     arithflag = 1;
2652     }
2653    
2654     if (ra == 0) {
2655     if (update)
2656     fatal("[ PPC WARNING: invalid Update form ]\n");
2657     addr = 0;
2658     } else
2659     addr = cpu->cd.ppc.gpr[ra];
2660    
2661     if (load && update && ra == rs)
2662     fatal("[ PPC WARNING: invalid Update load form ]\n");
2663    
2664     addr += imm;
2665    
2666     /* TODO: alignment check? */
2667    
2668     if (cpu->machine->instruction_trace) {
2669     if (cpu->cd.ppc.bits == 32)
2670     debug("\t[0x%08llx", (long long)addr);
2671     else
2672     debug("\t[0x%016llx", (long long)addr);
2673     }
2674    
2675     if (load) {
2676     r = cpu->memory_rw(cpu, cpu->mem, addr, tmp_data,
2677     tmp_data_len, MEM_READ, CACHE_DATA);
2678    
2679     if (r == MEMORY_ACCESS_OK) {
2680     tmp = 0;
2681     if (arithflag) {
2682     if (cpu->byte_order ==
2683     EMUL_BIG_ENDIAN) {
2684     if (tmp_data[0] & 0x80)
2685     tmp --;
2686     } else {
2687     if (tmp_data[tmp_data_len-1]
2688     & 0x80)
2689     tmp --;
2690     }
2691     }
2692     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2693     for (i=0; i<tmp_data_len; i++) {
2694     tmp <<= 8;
2695     tmp += tmp_data[i];
2696     }
2697     } else {
2698     for (i=0; i<tmp_data_len; i++) {
2699     tmp <<= 8;
2700     tmp += tmp_data[
2701     tmp_data_len - 1 -i];
2702     }
2703     }
2704    
2705     if (!fpreg)
2706     cpu->cd.ppc.gpr[rs] = tmp;
2707     else
2708     cpu->cd.ppc.fpr[rs] = tmp;
2709     }
2710     } else {
2711     if (!fpreg)
2712     tmp = cpu->cd.ppc.gpr[rs];
2713     else
2714     tmp = cpu->cd.ppc.fpr[rs];
2715    
2716     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2717     for (i=0; i<tmp_data_len; i++)
2718     tmp_data[tmp_data_len-1-i] =
2719     tmp >> (8*i);
2720     } else {
2721     for (i=0; i<tmp_data_len; i++)
2722     tmp_data[i] = tmp >> (8*i);
2723     }
2724    
2725     r = cpu->memory_rw(cpu, cpu->mem, addr, tmp_data,
2726     tmp_data_len, MEM_WRITE, CACHE_DATA);
2727     }
2728    
2729     if (cpu->machine->instruction_trace) {
2730     if (r == MEMORY_ACCESS_OK) {
2731     switch (tmp_data_len) {
2732     case 1: debug(", data = 0x%02x]\n", (int)tmp);
2733     break;
2734     case 2: debug(", data = 0x%04x]\n", (int)tmp);
2735     break;
2736     case 4: debug(", data = 0x%08x]\n", (int)tmp);
2737     break;
2738     default:debug(", data = 0x%016llx]\n",
2739     (long long)tmp);
2740     }
2741     } else
2742     debug(", FAILED]\n");
2743     }
2744    
2745     if (r != MEMORY_ACCESS_OK) {
2746     /* TODO: exception? */
2747     return 0;
2748     }
2749    
2750     if (update && ra != 0)
2751     cpu->cd.ppc.gpr[ra] = addr;
2752     break;
2753    
2754     case PPC_HI6_LMW:
2755     case PPC_HI6_STMW:
2756     /* NOTE: Loads use rt, not rs, but are otherwise similar
2757     to stores. This code uses rs for both. */
2758     rs = (iword >> 21) & 31;
2759     ra = (iword >> 16) & 31;
2760     imm = (int16_t)(iword & 0xffff);
2761    
2762     load = 1; tmp_data_len = 4;
2763    
2764     switch (hi6) {
2765     case PPC_HI6_STMW:
2766     load = 0;
2767     }
2768    
2769     if (ra == 0) {
2770     addr = 0;
2771     } else
2772     addr = cpu->cd.ppc.gpr[ra];
2773    
2774     if (load && rs == 0)
2775     fatal("[ PPC WARNING: invalid LMW form ]\n");
2776    
2777     addr += imm;
2778    
2779     /* TODO: alignment check? */
2780    
2781     if (cpu->machine->instruction_trace) {
2782     if (cpu->cd.ppc.bits == 32)
2783     debug("\t[0x%08llx", (long long)addr);
2784     else
2785     debug("\t[0x%016llx", (long long)addr);
2786     }
2787    
2788     /* There can be multiple errors! */
2789     r = 0;
2790    
2791     while (rs <= 31) {
2792     if (load) {
2793     if (cpu->memory_rw(cpu, cpu->mem, addr,
2794     tmp_data, tmp_data_len, MEM_READ,
2795     CACHE_DATA) != MEMORY_ACCESS_OK)
2796     r++;
2797    
2798     if (r == 0) {
2799     tmp = 0;
2800     if (cpu->byte_order ==
2801     EMUL_BIG_ENDIAN) {
2802     for (i=0; i<tmp_data_len; i++) {
2803     tmp <<= 8;
2804     tmp += tmp_data[i];
2805     }
2806     } else {
2807     for (i=0; i<tmp_data_len; i++) {
2808     tmp <<= 8;
2809     tmp += tmp_data[
2810     tmp_data_len - 1
2811     - i];
2812     }
2813     }
2814    
2815     cpu->cd.ppc.gpr[rs] = tmp;
2816     }
2817     } else {
2818     tmp = cpu->cd.ppc.gpr[rs];
2819    
2820     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2821     for (i=0; i<tmp_data_len; i++)
2822     tmp_data[tmp_data_len-1-i] =
2823     tmp >> (8*i);
2824     } else {
2825     for (i=0; i<tmp_data_len; i++)
2826     tmp_data[i] = tmp >> (8*i);
2827     }
2828    
2829     if (cpu->memory_rw(cpu, cpu->mem, addr,
2830     tmp_data, tmp_data_len, MEM_WRITE,
2831     CACHE_DATA) != MEMORY_ACCESS_OK)
2832     r ++;
2833     }
2834    
2835     /* TODO: Exception! */
2836    
2837     /* Go to next register, multiword... */
2838     rs ++;
2839     addr += tmp_data_len;
2840     }
2841    
2842     if (cpu->machine->instruction_trace) {
2843     if (r == 0) {
2844     debug(", data = ...]\n");
2845     } else
2846     debug(", FAILED]\n");
2847     }
2848    
2849     if (r > 0)
2850     return 0;
2851     break;
2852    
2853     default:
2854     fatal("[ unimplemented PPC hi6 = 0x%02x, pc = 0x%016llx ]\n",
2855     hi6, (long long) (cpu->cd.ppc.pc_last));
2856     cpu->running = 0;
2857     return 0;
2858     }
2859    
2860     return 1;
2861     }
2862    
2863    
2864     #define CPU_RUN ppc_cpu_run
2865     #define CPU_RINSTR ppc_cpu_run_instr
2866     #define CPU_RUN_PPC
2867     #include "cpu_run.c"
2868     #undef CPU_RINSTR
2869     #undef CPU_RUN_PPC
2870     #undef CPU_RUN
2871    
2872    
2873     #define MEMORY_RW ppc_memory_rw
2874     #define MEM_PPC
2875     #include "memory_rw.c"
2876     #undef MEM_PPC
2877     #undef MEMORY_RW
2878    
2879    
2880     /*
2881     * ppc_cpu_family_init():
2882     *
2883     * Fill in the cpu_family struct for PPC.
2884     */
2885     int ppc_cpu_family_init(struct cpu_family *fp)
2886     {
2887     fp->name = "PPC";
2888     fp->cpu_new = ppc_cpu_new;
2889     fp->list_available_types = ppc_cpu_list_available_types;
2890     fp->register_match = ppc_cpu_register_match;
2891     fp->disassemble_instr = ppc_cpu_disassemble_instr;
2892     fp->register_dump = ppc_cpu_register_dump;
2893     fp->run = ppc_cpu_run;
2894     fp->dumpinfo = ppc_cpu_dumpinfo;
2895     /* fp->show_full_statistics = ppc_cpu_show_full_statistics; */
2896     /* fp->tlbdump = ppc_cpu_tlbdump; */
2897     /* fp->interrupt = ppc_cpu_interrupt; */
2898     /* fp->interrupt_ack = ppc_cpu_interrupt_ack; */
2899     return 1;
2900     }
2901    
2902    
2903     #endif /* ENABLE_PPC */

  ViewVC Help
Powered by ViewVC 1.1.26