/[gxemul]/trunk/src/cpus/cpu_sparc_instr.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

Contents of /trunk/src/cpus/cpu_sparc_instr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (show annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 45218 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1480 2007/02/19 01:34:42 debug Exp $
20061029	Changing usleep(1) calls in the debugger to usleep(10000)
20061107	Adding a new disk image option (-d o...) which sets the ISO9660
		filesystem base offset; also making some other hacks to allow
		NetBSD/dreamcast and homebrew demos/games to boot directly
		from a filesystem image.
		Moving Dreamcast-specific stuff in the documentation to its
		own page (dreamcast.html).
		Adding a border to the Dreamcast PVR framebuffer.
20061108	Adding a -T command line option (again?), for halting the
		emulator on unimplemented memory accesses.
20061109	Continuing on various SH4 and Dreamcast related things.
		The emulator should now halt on more unimplemented device
		accesses, instead of just printing a warning, forcing me to
		actually implement missing stuff :)
20061111	Continuing on SH4 and Dreamcast stuff.
		Adding a bogus Landisk (SH4) machine mode.
20061112	Implementing some parts of the Dreamcast GDROM device. With
		some ugly hacks, NetBSD can (barely) mount an ISO image.
20061113	NetBSD/dreamcast now starts booting from the Live CD image,
		but crashes randomly quite early on in the boot process.
20061122	Beginning on a skeleton interrupt.h and interrupt.c for the
		new interrupt subsystem.
20061124	Continuing on the new interrupt system; taking the first steps
		to attempt to connect CPUs (SuperH and MIPS) and devices
		(dev_cons and SH4 timer interrupts) to it. Many things will
		probably break from now on.
20061125	Converting dev_ns16550, dev_8253 to the new interrupt system.
		Attempting to begin to convert the ISA bus.
20061130	Incorporating a patch from Brian Foley for the configure
		script, which checks for X11 libs in /usr/X11R6/lib64 (which
		is used on some Linux systems).
20061227	Adding a note in the man page about booting from Dreamcast
		CDROM images (i.e. that no external kernel is needed).
20061229	Continuing on the interrupt system rewrite: beginning to
		convert more devices, adding abort() calls for legacy interrupt
		system calls so that everything now _has_ to be rewritten!
		Almost all machine modes are now completely broken.
20061230	More progress on removing old interrupt code, mostly related
		to the ISA bus + devices, the LCA bus (on AlphaBook1), and
		the Footbridge bus (for CATS). And some minor PCI stuff.
		Connecting the ARM cpu to the new interrupt system.
		The CATS, NetWinder, and QEMU_MIPS machine modes now work with
		the new interrupt system :)
20061231	Connecting PowerPC CPUs to the new interrupt system.
		Making PReP machines (IBM 6050) work again.
		Beginning to convert the GT PCI controller (for e.g. Malta
		and Cobalt emulation). Some things work, but not everything.
		Updating Copyright notices for 2007.
20070101	Converting dev_kn02 from legacy style to devinit; the 3max
		machine mode now works with the new interrupt system :-]
20070105	Beginning to convert the SGI O2 machine to the new interrupt
		system; finally converting O2 (IP32) devices to devinit, etc.
20070106	Continuing on the interrupt system redesign/rewrite; KN01
		(PMAX), KN230, and Dreamcast ASIC interrupts should work again,
		moving out stuff from machine.h and devices.h into the
		corresponding devices, beginning the rewrite of i80321
		interrupts, etc.
20070107	Beginning on the rewrite of Eagle interrupt stuff (PReP, etc).
20070117	Beginning the rewrite of Algor (V3) interrupts (finally
		changing dev_v3 into devinit style).
20070118	Removing the "bus" registry concept from machine.h, because
		it was practically meaningless.
		Continuing on the rewrite of Algor V3 ISA interrupts.
20070121	More work on Algor interrupts; they are now working again,
		well enough to run NetBSD/algor. :-)
20070122	Converting VR41xx (HPCmips) interrupts. NetBSD/hpcmips
		can be installed using the new interrupt system :-)
20070123	Making the testmips mode work with the new interrupt system.
20070127	Beginning to convert DEC5800 devices to devinit, and to the
		new interrupt system.
		Converting Playstation 2 devices to devinit, and converting
		the interrupt system. Also fixing a severe bug: the interrupt
		mask register on Playstation 2 is bitwise _toggled_ on writes.
20070128	Removing the dummy NetGear machine mode and the 8250 device
		(which was only used by the NetGear machine).
		Beginning to convert the MacPPC GC (Grand Central) interrupt
		controller to the new interrupt system.
		Converting Jazz interrupts (PICA61 etc.) to the new interrupt
		system. NetBSD/arc can be installed again :-)
		Fixing the JAZZ timer (hardcoding it at 100 Hz, works with
		NetBSD and it is better than a completely dummy timer as it
		was before).
		Converting dev_mp to the new interrupt system, although I
		haven't had time to actually test it yet.
		Completely removing src/machines/interrupts.c, cpu_interrupt
		and cpu_interrupt_ack in src/cpu.c, and
		src/include/machine_interrupts.h! Adding fatal error messages
		+ abort() in the few places that are left to fix.
		Converting dev_z8530 to the new interrupt system.
		FINALLY removing the md_int struct completely from the
		machine struct.
		SH4 fixes (adding a PADDR invalidation in the ITLB replacement
		code in memory_sh.c); the NetBSD/dreamcast LiveCD now runs
		all the way to the login prompt, and can be interacted with :-)
		Converting the CPC700 controller (PCI and interrupt controller
		for PM/PPC) to the new interrupt system.
20070129	Fixing MACE ISA interrupts (SGI IP32 emulation). Both NetBSD/
		sgimips' and OpenBSD/sgi's ramdisk kernels can now be
		interacted with again.
20070130	Moving out the MIPS multi_lw and _sw instruction combinations
		so that they are auto-generated at compile time instead.
20070131	Adding detection of amd64/x86_64 hosts in the configure script,
		for doing initial experiments (again :-) with native code
		generation.
		Adding a -k command line option to set the size of the dyntrans
		cache, and a -B command line option to disable native code
		generation, even if GXemul was compiled with support for
		native code generation for the specific host CPU architecture.
20070201	Experimenting with a skeleton for native code generation.
		Changing the default behaviour, so that native code generation
		is now disabled by default, and has to be enabled by using
		-b on the command line.
20070202	Continuing the native code generation experiments.
		Making PCI interrupts work for Footbridge again.
20070203	More native code generation experiments.
		Removing most of the native code generation experimental code,
		it does not make sense to include any quick hacks like this.
		Minor cleanup/removal of some more legacy MIPS interrupt code.
20070204	Making i80321 interrupts work again (for NetBSD/evbarm etc.),
		and fixing the timer at 100 Hz.
20070206	Experimenting with removing the wdc interrupt slowness hack.
20070207	Lowering the number of dyntrans TLB entries for MIPS from
		192 to 128, resulting in a minor speed improvement.
		Minor optimization to the code invalidation routine in
		cpu_dyntrans.c.
20070208	Increasing (experimentally) the nr of dyntrans instructions per
		loop from 60 to 120.
20070210	Commenting out (experimentally) the dyntrans_device_danger
		detection in memory_rw.c.
		Changing the testmips and baremips machines to use a revision 2
		MIPS64 CPU by default, instead of revision 1.
		Removing the dummy i960, IA64, x86, AVR32, and HP PA-RISC
		files, the PC bios emulation, and the Olivetti M700 (ARC) and
		db64360 emulation modes.
20070211	Adding an "mp" demo to the demos directory, which tests the
		SMP functionality of the testmips machine.
		Fixing PReP interrupts some more. NetBSD/prep now boots again.
20070216	Adding a "nop workaround" for booting Mach/PMAX to the
		documentation; thanks to Artur Bujdoso for the values.
		Converting more of the MacPPC interrupt stuff to the new
		system.
		Beginning to convert BeBox interrupts to the new system.
		PPC603e should NOT have the PPC_NO_DEC flag! Removing it.
		Correcting BeBox clock speed (it was set to 100 in the NetBSD
		bootinfo block, but should be 33000000/4), allowing NetBSD
		to start without using the (incorrect) PPC_NO_DEC hack.
20070217	Implementing (slow) AltiVec vector loads and stores, allowing
		NetBSD/macppc to finally boot using the GENERIC kernel :-)
		Updating the documentation with install instructions for
		NetBSD/macppc.
20070218-19	Regression testing for the release.

==============  RELEASE 0.4.4  ==============


1 /*
2 * Copyright (C) 2005-2007 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_sparc_instr.c,v 1.26 2006/12/30 13:30:55 debug Exp $
29 *
30 * SPARC instructions.
31 *
32 * Individual functions should keep track of cpu->n_translated_instrs.
33 * (If no instruction was executed, then it should be decreased. If, say, 4
34 * instructions were combined into one function and executed, then it should
35 * be increased by 3.)
36 */
37
38
39 /*
40 * invalid: For catching bugs.
41 */
42 X(invalid)
43 {
44 fatal("FATAL ERROR: An internal error occured in the SPARC"
45 " dyntrans code. Please contact the author with detailed"
46 " repro steps on how to trigger this bug.\n");
47 exit(1);
48 }
49
50
51 /*
52 * nop: Do nothing.
53 */
54 X(nop)
55 {
56 }
57
58
59 /*****************************************************************************/
60
61
62 /*
63 * call
64 *
65 * arg[0] = int32_t displacement compared to the current instruction
66 * arg[1] = int32_t displacement of current instruction compared to
67 * start of the page
68 */
69 X(call)
70 {
71 MODE_uint_t old_pc = cpu->pc;
72 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
73 << SPARC_INSTR_ALIGNMENT_SHIFT);
74 old_pc += (int32_t)ic->arg[1];
75 cpu->cd.sparc.r[SPARC_REG_O7] = old_pc;
76 cpu->delay_slot = TO_BE_DELAYED;
77 ic[1].f(cpu, ic+1);
78 cpu->n_translated_instrs ++;
79 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
80 /* Note: Must be non-delayed when jumping to the new pc: */
81 cpu->delay_slot = NOT_DELAYED;
82 cpu->pc = old_pc + (int32_t)ic->arg[0];
83 quick_pc_to_pointers(cpu);
84 } else
85 cpu->delay_slot = NOT_DELAYED;
86 }
87 X(call_trace)
88 {
89 MODE_uint_t old_pc = cpu->pc;
90 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
91 << SPARC_INSTR_ALIGNMENT_SHIFT);
92 old_pc += (int32_t)ic->arg[1];
93 cpu->cd.sparc.r[SPARC_REG_O7] = old_pc;
94 cpu->delay_slot = TO_BE_DELAYED;
95 ic[1].f(cpu, ic+1);
96 cpu->n_translated_instrs ++;
97 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
98 /* Note: Must be non-delayed when jumping to the new pc: */
99 cpu->delay_slot = NOT_DELAYED;
100 cpu->pc = old_pc + (int32_t)ic->arg[0];
101 cpu_functioncall_trace(cpu, cpu->pc);
102 quick_pc_to_pointers(cpu);
103 } else
104 cpu->delay_slot = NOT_DELAYED;
105 }
106
107
108 /*
109 * bl
110 *
111 * arg[0] = int32_t displacement compared to the start of the current page
112 */
113 X(bl)
114 {
115 MODE_uint_t old_pc = cpu->pc;
116 int n = (cpu->cd.sparc.ccr & SPARC_CCR_N) ? 1 : 0;
117 int v = (cpu->cd.sparc.ccr & SPARC_CCR_V) ? 1 : 0;
118 int cond = n ^ v;
119 cpu->delay_slot = TO_BE_DELAYED;
120 ic[1].f(cpu, ic+1);
121 cpu->n_translated_instrs ++;
122 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
123 /* Note: Must be non-delayed when jumping to the new pc: */
124 cpu->delay_slot = NOT_DELAYED;
125 if (cond) {
126 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
127 << SPARC_INSTR_ALIGNMENT_SHIFT);
128 cpu->pc = old_pc + (int32_t)ic->arg[0];
129 quick_pc_to_pointers(cpu);
130 }
131 } else
132 cpu->delay_slot = NOT_DELAYED;
133 }
134 X(bl_xcc)
135 {
136 MODE_uint_t old_pc = cpu->pc;
137 int n = ((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT) & SPARC_CCR_N)? 1:0;
138 int v = ((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT) & SPARC_CCR_V)? 1:0;
139 int cond = n ^ v;
140 cpu->delay_slot = TO_BE_DELAYED;
141 ic[1].f(cpu, ic+1);
142 cpu->n_translated_instrs ++;
143 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
144 /* Note: Must be non-delayed when jumping to the new pc: */
145 cpu->delay_slot = NOT_DELAYED;
146 if (cond) {
147 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
148 << SPARC_INSTR_ALIGNMENT_SHIFT);
149 cpu->pc = old_pc + (int32_t)ic->arg[0];
150 quick_pc_to_pointers(cpu);
151 }
152 } else
153 cpu->delay_slot = NOT_DELAYED;
154 }
155
156
157 /*
158 * ble
159 *
160 * arg[0] = int32_t displacement compared to the start of the current page
161 */
162 X(ble)
163 {
164 MODE_uint_t old_pc = cpu->pc;
165 int n = (cpu->cd.sparc.ccr & SPARC_CCR_N) ? 1 : 0;
166 int v = (cpu->cd.sparc.ccr & SPARC_CCR_V) ? 1 : 0;
167 int z = (cpu->cd.sparc.ccr & SPARC_CCR_Z) ? 1 : 0;
168 int cond = (n ^ v) || z;
169 cpu->delay_slot = TO_BE_DELAYED;
170 ic[1].f(cpu, ic+1);
171 cpu->n_translated_instrs ++;
172 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
173 /* Note: Must be non-delayed when jumping to the new pc: */
174 cpu->delay_slot = NOT_DELAYED;
175 if (cond) {
176 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
177 << SPARC_INSTR_ALIGNMENT_SHIFT);
178 cpu->pc = old_pc + (int32_t)ic->arg[0];
179 quick_pc_to_pointers(cpu);
180 }
181 } else
182 cpu->delay_slot = NOT_DELAYED;
183 }
184 X(ble_xcc)
185 {
186 MODE_uint_t old_pc = cpu->pc;
187 int n = ((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT) & SPARC_CCR_N)? 1:0;
188 int v = ((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT) & SPARC_CCR_V)? 1:0;
189 int z = ((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT) & SPARC_CCR_Z)? 1:0;
190 int cond = (n ^ v) || z;
191 cpu->delay_slot = TO_BE_DELAYED;
192 ic[1].f(cpu, ic+1);
193 cpu->n_translated_instrs ++;
194 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
195 /* Note: Must be non-delayed when jumping to the new pc: */
196 cpu->delay_slot = NOT_DELAYED;
197 if (cond) {
198 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
199 << SPARC_INSTR_ALIGNMENT_SHIFT);
200 cpu->pc = old_pc + (int32_t)ic->arg[0];
201 quick_pc_to_pointers(cpu);
202 }
203 } else
204 cpu->delay_slot = NOT_DELAYED;
205 }
206
207
208 /*
209 * bne
210 *
211 * arg[0] = int32_t displacement compared to the start of the current page
212 */
213 X(bne)
214 {
215 MODE_uint_t old_pc = cpu->pc;
216 int cond = (cpu->cd.sparc.ccr & SPARC_CCR_Z) ? 0 : 1;
217 cpu->delay_slot = TO_BE_DELAYED;
218 ic[1].f(cpu, ic+1);
219 cpu->n_translated_instrs ++;
220 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
221 /* Note: Must be non-delayed when jumping to the new pc: */
222 cpu->delay_slot = NOT_DELAYED;
223 if (cond) {
224 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
225 << SPARC_INSTR_ALIGNMENT_SHIFT);
226 cpu->pc = old_pc + (int32_t)ic->arg[0];
227 quick_pc_to_pointers(cpu);
228 }
229 } else
230 cpu->delay_slot = NOT_DELAYED;
231 }
232 X(bne_a)
233 {
234 MODE_uint_t old_pc = cpu->pc;
235 int cond = (cpu->cd.sparc.ccr & SPARC_CCR_Z) ? 0 : 1;
236 cpu->delay_slot = TO_BE_DELAYED;
237 if (!cond) {
238 /* Nullify the delay slot: */
239 cpu->cd.sparc.next_ic ++;
240 return;
241 }
242 ic[1].f(cpu, ic+1);
243 cpu->n_translated_instrs ++;
244 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
245 /* Note: Must be non-delayed when jumping to the new pc: */
246 cpu->delay_slot = NOT_DELAYED;
247 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
248 << SPARC_INSTR_ALIGNMENT_SHIFT);
249 cpu->pc = old_pc + (int32_t)ic->arg[0];
250 quick_pc_to_pointers(cpu);
251 } else
252 cpu->delay_slot = NOT_DELAYED;
253 }
254
255
256 /*
257 * bg
258 *
259 * arg[0] = int32_t displacement compared to the start of the current page
260 */
261 X(bg)
262 {
263 MODE_uint_t old_pc = cpu->pc;
264 int n = (cpu->cd.sparc.ccr & SPARC_CCR_N) ? 1 : 0;
265 int v = (cpu->cd.sparc.ccr & SPARC_CCR_V) ? 1 : 0;
266 int z = (cpu->cd.sparc.ccr & SPARC_CCR_Z) ? 1 : 0;
267 int cond = !(z | (n ^ v));
268 cpu->delay_slot = TO_BE_DELAYED;
269 ic[1].f(cpu, ic+1);
270 cpu->n_translated_instrs ++;
271 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
272 /* Note: Must be non-delayed when jumping to the new pc: */
273 cpu->delay_slot = NOT_DELAYED;
274 if (cond) {
275 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
276 << SPARC_INSTR_ALIGNMENT_SHIFT);
277 cpu->pc = old_pc + (int32_t)ic->arg[0];
278 quick_pc_to_pointers(cpu);
279 }
280 } else
281 cpu->delay_slot = NOT_DELAYED;
282 }
283 X(bg_xcc)
284 {
285 MODE_uint_t old_pc = cpu->pc;
286 int n = ((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT) & SPARC_CCR_N)? 1:0;
287 int v = ((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT) & SPARC_CCR_V)? 1:0;
288 int z = ((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT) & SPARC_CCR_Z)? 1:0;
289 int cond = !(z | (n ^ v));
290 cpu->delay_slot = TO_BE_DELAYED;
291 ic[1].f(cpu, ic+1);
292 cpu->n_translated_instrs ++;
293 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
294 /* Note: Must be non-delayed when jumping to the new pc: */
295 cpu->delay_slot = NOT_DELAYED;
296 if (cond) {
297 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
298 << SPARC_INSTR_ALIGNMENT_SHIFT);
299 cpu->pc = old_pc + (int32_t)ic->arg[0];
300 quick_pc_to_pointers(cpu);
301 }
302 } else
303 cpu->delay_slot = NOT_DELAYED;
304 }
305
306
307 /*
308 * bge
309 *
310 * arg[0] = int32_t displacement compared to the start of the current page
311 */
312 X(bge)
313 {
314 MODE_uint_t old_pc = cpu->pc;
315 int n = (cpu->cd.sparc.ccr & SPARC_CCR_N) ? 1 : 0;
316 int v = (cpu->cd.sparc.ccr & SPARC_CCR_V) ? 1 : 0;
317 int cond = !(n ^ v);
318 cpu->delay_slot = TO_BE_DELAYED;
319 ic[1].f(cpu, ic+1);
320 cpu->n_translated_instrs ++;
321 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
322 /* Note: Must be non-delayed when jumping to the new pc: */
323 cpu->delay_slot = NOT_DELAYED;
324 if (cond) {
325 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
326 << SPARC_INSTR_ALIGNMENT_SHIFT);
327 cpu->pc = old_pc + (int32_t)ic->arg[0];
328 quick_pc_to_pointers(cpu);
329 }
330 } else
331 cpu->delay_slot = NOT_DELAYED;
332 }
333 X(bge_xcc)
334 {
335 MODE_uint_t old_pc = cpu->pc;
336 int n = ((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT) & SPARC_CCR_N)? 1:0;
337 int v = ((cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT) & SPARC_CCR_V)? 1:0;
338 int cond = !(n ^ v);
339 cpu->delay_slot = TO_BE_DELAYED;
340 ic[1].f(cpu, ic+1);
341 cpu->n_translated_instrs ++;
342 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
343 /* Note: Must be non-delayed when jumping to the new pc: */
344 cpu->delay_slot = NOT_DELAYED;
345 if (cond) {
346 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
347 << SPARC_INSTR_ALIGNMENT_SHIFT);
348 cpu->pc = old_pc + (int32_t)ic->arg[0];
349 quick_pc_to_pointers(cpu);
350 }
351 } else
352 cpu->delay_slot = NOT_DELAYED;
353 }
354
355
356 /*
357 * be
358 *
359 * arg[0] = int32_t displacement compared to the start of the current page
360 */
361 X(be)
362 {
363 MODE_uint_t old_pc = cpu->pc;
364 int cond = cpu->cd.sparc.ccr & SPARC_CCR_Z;
365 cpu->delay_slot = TO_BE_DELAYED;
366 ic[1].f(cpu, ic+1);
367 cpu->n_translated_instrs ++;
368 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
369 /* Note: Must be non-delayed when jumping to the new pc: */
370 cpu->delay_slot = NOT_DELAYED;
371 if (cond) {
372 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
373 << SPARC_INSTR_ALIGNMENT_SHIFT);
374 cpu->pc = old_pc + (int32_t)ic->arg[0];
375 quick_pc_to_pointers(cpu);
376 }
377 } else
378 cpu->delay_slot = NOT_DELAYED;
379 }
380 X(be_xcc)
381 {
382 MODE_uint_t old_pc = cpu->pc;
383 int cond = (cpu->cd.sparc.ccr >> SPARC_CCR_XCC_SHIFT) & SPARC_CCR_Z;
384 cpu->delay_slot = TO_BE_DELAYED;
385 ic[1].f(cpu, ic+1);
386 cpu->n_translated_instrs ++;
387 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
388 /* Note: Must be non-delayed when jumping to the new pc: */
389 cpu->delay_slot = NOT_DELAYED;
390 if (cond) {
391 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
392 << SPARC_INSTR_ALIGNMENT_SHIFT);
393 cpu->pc = old_pc + (int32_t)ic->arg[0];
394 quick_pc_to_pointers(cpu);
395 }
396 } else
397 cpu->delay_slot = NOT_DELAYED;
398 }
399
400
401 /*
402 * ba
403 *
404 * arg[0] = int32_t displacement compared to the start of the current page
405 */
406 X(ba)
407 {
408 MODE_uint_t old_pc = cpu->pc;
409 cpu->delay_slot = TO_BE_DELAYED;
410 ic[1].f(cpu, ic+1);
411 cpu->n_translated_instrs ++;
412 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
413 /* Note: Must be non-delayed when jumping to the new pc: */
414 cpu->delay_slot = NOT_DELAYED;
415 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
416 << SPARC_INSTR_ALIGNMENT_SHIFT);
417 cpu->pc = old_pc + (int32_t)ic->arg[0];
418 quick_pc_to_pointers(cpu);
419 } else
420 cpu->delay_slot = NOT_DELAYED;
421 }
422
423
424 /*
425 * brnz
426 *
427 * arg[0] = int32_t displacement compared to the start of the current page
428 * arg[1] = ptr to rs1
429 */
430 X(brnz)
431 {
432 MODE_uint_t old_pc = cpu->pc;
433 int cond = reg(ic->arg[1]) != 0;
434 cpu->delay_slot = TO_BE_DELAYED;
435 ic[1].f(cpu, ic+1);
436 cpu->n_translated_instrs ++;
437 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
438 /* Note: Must be non-delayed when jumping to the new pc: */
439 cpu->delay_slot = NOT_DELAYED;
440 if (cond) {
441 old_pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
442 << SPARC_INSTR_ALIGNMENT_SHIFT);
443 cpu->pc = old_pc + (int32_t)ic->arg[0];
444 quick_pc_to_pointers(cpu);
445 }
446 } else
447 cpu->delay_slot = NOT_DELAYED;
448 }
449
450
451 /*
452 * Save:
453 *
454 * arg[0] = ptr to rs1
455 * arg[1] = ptr to rs2 or an immediate value (int32_t)
456 * arg[2] = ptr to rd (_after_ the register window change)
457 */
458 X(save_v9_imm)
459 {
460 MODE_uint_t rs = reg(ic->arg[0]) + (int32_t)ic->arg[1];
461 int cwp = cpu->cd.sparc.cwp;
462
463 if (cpu->cd.sparc.cansave == 0) {
464 fatal("save_v9_imm: spill trap. TODO\n");
465 exit(1);
466 }
467
468 if (cpu->cd.sparc.cleanwin - cpu->cd.sparc.canrestore == 0) {
469 fatal("save_v9_imm: clean_window trap. TODO\n");
470 exit(1);
471 }
472
473 /* Save away old in registers: */
474 memcpy(&cpu->cd.sparc.r_inout[cwp][0], &cpu->cd.sparc.r[SPARC_REG_I0],
475 sizeof(cpu->cd.sparc.r[SPARC_REG_I0]) * N_SPARC_INOUT_REG);
476
477 /* Save away old local registers: */
478 memcpy(&cpu->cd.sparc.r_local[cwp][0], &cpu->cd.sparc.r[SPARC_REG_L0],
479 sizeof(cpu->cd.sparc.r[SPARC_REG_L0]) * N_SPARC_INOUT_REG);
480
481 cpu->cd.sparc.cwp = (cwp + 1) % cpu->cd.sparc.cpu_type.nwindows;
482 cpu->cd.sparc.cansave --;
483 cpu->cd.sparc.canrestore ++; /* TODO: modulo here too? */
484 cwp = cpu->cd.sparc.cwp;
485
486 /* The out registers become the new in registers: */
487 memcpy(&cpu->cd.sparc.r[SPARC_REG_I0], &cpu->cd.sparc.r[SPARC_REG_O0],
488 sizeof(cpu->cd.sparc.r[SPARC_REG_O0]) * N_SPARC_INOUT_REG);
489
490 /* Read new local registers: */
491 memcpy(&cpu->cd.sparc.r[SPARC_REG_L0], &cpu->cd.sparc.r_local[cwp][0],
492 sizeof(cpu->cd.sparc.r[SPARC_REG_L0]) * N_SPARC_INOUT_REG);
493
494 reg(ic->arg[2]) = rs;
495 }
496
497
498 /*
499 * Restore:
500 */
501 X(restore)
502 {
503 int cwp = cpu->cd.sparc.cwp;
504
505 if (cpu->cd.sparc.canrestore == 0) {
506 fatal("restore: spill trap. TODO\n");
507 exit(1);
508 }
509
510 cpu->cd.sparc.cwp = cwp - 1;
511 if (cwp == 0)
512 cpu->cd.sparc.cwp = cpu->cd.sparc.cpu_type.nwindows - 1;
513 cpu->cd.sparc.cansave ++;
514 cpu->cd.sparc.canrestore --;
515 cwp = cpu->cd.sparc.cwp;
516
517 /* The in registers become the new out registers: */
518 memcpy(&cpu->cd.sparc.r[SPARC_REG_O0], &cpu->cd.sparc.r[SPARC_REG_I0],
519 sizeof(cpu->cd.sparc.r[SPARC_REG_O0]) * N_SPARC_INOUT_REG);
520
521 /* Read back the local registers: */
522 memcpy(&cpu->cd.sparc.r[SPARC_REG_L0], &cpu->cd.sparc.r_local[cwp][0],
523 sizeof(cpu->cd.sparc.r[SPARC_REG_L0]) * N_SPARC_INOUT_REG);
524
525 /* Read back the in registers: */
526 memcpy(&cpu->cd.sparc.r[SPARC_REG_I0], &cpu->cd.sparc.r_inout[cwp][0],
527 sizeof(cpu->cd.sparc.r[SPARC_REG_I0]) * N_SPARC_INOUT_REG);
528 }
529
530
531 /*
532 * Jump and link
533 *
534 * arg[0] = ptr to rs1
535 * arg[1] = ptr to rs2 or an immediate value (int32_t)
536 * arg[2] = ptr to rd
537 */
538 X(jmpl_imm)
539 {
540 int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
541 / sizeof(struct sparc_instr_call);
542 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
543 << SPARC_INSTR_ALIGNMENT_SHIFT);
544 cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
545 reg(ic->arg[2]) = cpu->pc;
546
547 cpu->delay_slot = TO_BE_DELAYED;
548 ic[1].f(cpu, ic+1);
549 cpu->n_translated_instrs ++;
550
551 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
552 /* Note: Must be non-delayed when jumping to the new pc: */
553 cpu->delay_slot = NOT_DELAYED;
554 cpu->pc = reg(ic->arg[0]) + (int32_t)ic->arg[1];
555 quick_pc_to_pointers(cpu);
556 } else
557 cpu->delay_slot = NOT_DELAYED;
558 }
559 X(jmpl_imm_no_rd)
560 {
561 int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
562 / sizeof(struct sparc_instr_call);
563 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
564 << SPARC_INSTR_ALIGNMENT_SHIFT);
565 cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
566
567 cpu->delay_slot = TO_BE_DELAYED;
568 ic[1].f(cpu, ic+1);
569 cpu->n_translated_instrs ++;
570
571 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
572 /* Note: Must be non-delayed when jumping to the new pc: */
573 cpu->delay_slot = NOT_DELAYED;
574 cpu->pc = reg(ic->arg[0]) + (int32_t)ic->arg[1];
575 quick_pc_to_pointers(cpu);
576 } else
577 cpu->delay_slot = NOT_DELAYED;
578 }
579 X(jmpl_reg)
580 {
581 int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
582 / sizeof(struct sparc_instr_call);
583 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
584 << SPARC_INSTR_ALIGNMENT_SHIFT);
585 cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
586 reg(ic->arg[2]) = cpu->pc;
587
588 cpu->delay_slot = TO_BE_DELAYED;
589 ic[1].f(cpu, ic+1);
590 cpu->n_translated_instrs ++;
591
592 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
593 /* Note: Must be non-delayed when jumping to the new pc: */
594 cpu->delay_slot = NOT_DELAYED;
595 cpu->pc = reg(ic->arg[0]) + reg(ic->arg[1]);
596 quick_pc_to_pointers(cpu);
597 } else
598 cpu->delay_slot = NOT_DELAYED;
599 }
600 X(jmpl_reg_no_rd)
601 {
602 int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
603 / sizeof(struct sparc_instr_call);
604 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
605 << SPARC_INSTR_ALIGNMENT_SHIFT);
606 cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
607
608 cpu->delay_slot = TO_BE_DELAYED;
609 ic[1].f(cpu, ic+1);
610 cpu->n_translated_instrs ++;
611
612 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
613 /* Note: Must be non-delayed when jumping to the new pc: */
614 cpu->delay_slot = NOT_DELAYED;
615 cpu->pc = reg(ic->arg[0]) + reg(ic->arg[1]);
616 quick_pc_to_pointers(cpu);
617 } else
618 cpu->delay_slot = NOT_DELAYED;
619 }
620
621
622 X(jmpl_imm_trace)
623 {
624 int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
625 / sizeof(struct sparc_instr_call);
626 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
627 << SPARC_INSTR_ALIGNMENT_SHIFT);
628 cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
629 reg(ic->arg[2]) = cpu->pc;
630
631 cpu->delay_slot = TO_BE_DELAYED;
632 ic[1].f(cpu, ic+1);
633 cpu->n_translated_instrs ++;
634
635 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
636 /* Note: Must be non-delayed when jumping to the new pc: */
637 cpu->delay_slot = NOT_DELAYED;
638 cpu->pc = reg(ic->arg[0]) + (int32_t)ic->arg[1];
639 cpu_functioncall_trace(cpu, cpu->pc);
640 quick_pc_to_pointers(cpu);
641 } else
642 cpu->delay_slot = NOT_DELAYED;
643 }
644 X(jmpl_reg_trace)
645 {
646 int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
647 / sizeof(struct sparc_instr_call);
648 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
649 << SPARC_INSTR_ALIGNMENT_SHIFT);
650 cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
651 reg(ic->arg[2]) = cpu->pc;
652
653 cpu->delay_slot = TO_BE_DELAYED;
654 ic[1].f(cpu, ic+1);
655 cpu->n_translated_instrs ++;
656
657 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
658 /* Note: Must be non-delayed when jumping to the new pc: */
659 cpu->delay_slot = NOT_DELAYED;
660 cpu->pc = reg(ic->arg[0]) + reg(ic->arg[1]);
661 cpu_functioncall_trace(cpu, cpu->pc);
662 quick_pc_to_pointers(cpu);
663 } else
664 cpu->delay_slot = NOT_DELAYED;
665 }
666 X(retl_trace)
667 {
668 int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
669 / sizeof(struct sparc_instr_call);
670 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
671 << SPARC_INSTR_ALIGNMENT_SHIFT);
672 cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
673
674 cpu->delay_slot = TO_BE_DELAYED;
675 ic[1].f(cpu, ic+1);
676 cpu->n_translated_instrs ++;
677
678 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
679 /* Note: Must be non-delayed when jumping to the new pc: */
680 cpu->delay_slot = NOT_DELAYED;
681 cpu->pc = reg(ic->arg[0]) + (int32_t)ic->arg[1];
682 quick_pc_to_pointers(cpu);
683 cpu_functioncall_trace_return(cpu);
684 } else
685 cpu->delay_slot = NOT_DELAYED;
686 }
687
688
689 /*
690 * Return
691 *
692 * arg[0] = ptr to rs1
693 * arg[1] = ptr to rs2 or an immediate value (int32_t)
694 */
695 X(return_imm)
696 {
697 int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
698 / sizeof(struct sparc_instr_call);
699 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
700 << SPARC_INSTR_ALIGNMENT_SHIFT);
701 cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
702
703 cpu->delay_slot = TO_BE_DELAYED;
704 ic[1].f(cpu, ic+1);
705 cpu->n_translated_instrs ++;
706
707 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
708 /* Note: Must be non-delayed when jumping to the new pc: */
709 cpu->delay_slot = NOT_DELAYED;
710 cpu->pc = reg(ic->arg[0]) + (int32_t)ic->arg[1];
711 quick_pc_to_pointers(cpu);
712 instr(restore)(cpu, ic);
713 } else
714 cpu->delay_slot = NOT_DELAYED;
715 }
716 X(return_reg)
717 {
718 int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
719 / sizeof(struct sparc_instr_call);
720 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
721 << SPARC_INSTR_ALIGNMENT_SHIFT);
722 cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
723
724 cpu->delay_slot = TO_BE_DELAYED;
725 ic[1].f(cpu, ic+1);
726 cpu->n_translated_instrs ++;
727
728 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
729 /* Note: Must be non-delayed when jumping to the new pc: */
730 cpu->delay_slot = NOT_DELAYED;
731 cpu->pc = reg(ic->arg[0]) + reg(ic->arg[1]);
732 quick_pc_to_pointers(cpu);
733 instr(restore)(cpu, ic);
734 } else
735 cpu->delay_slot = NOT_DELAYED;
736 }
737 X(return_imm_trace)
738 {
739 int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
740 / sizeof(struct sparc_instr_call);
741 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
742 << SPARC_INSTR_ALIGNMENT_SHIFT);
743 cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
744
745 cpu->delay_slot = TO_BE_DELAYED;
746 ic[1].f(cpu, ic+1);
747 cpu->n_translated_instrs ++;
748
749 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
750 /* Note: Must be non-delayed when jumping to the new pc: */
751 cpu->delay_slot = NOT_DELAYED;
752 cpu->pc = reg(ic->arg[0]) + (int32_t)ic->arg[1];
753 cpu_functioncall_trace(cpu, cpu->pc);
754 quick_pc_to_pointers(cpu);
755 instr(restore)(cpu, ic);
756 } else
757 cpu->delay_slot = NOT_DELAYED;
758 }
759 X(return_reg_trace)
760 {
761 int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
762 / sizeof(struct sparc_instr_call);
763 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
764 << SPARC_INSTR_ALIGNMENT_SHIFT);
765 cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
766
767 cpu->delay_slot = TO_BE_DELAYED;
768 ic[1].f(cpu, ic+1);
769 cpu->n_translated_instrs ++;
770
771 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
772 /* Note: Must be non-delayed when jumping to the new pc: */
773 cpu->delay_slot = NOT_DELAYED;
774 cpu->pc = reg(ic->arg[0]) + reg(ic->arg[1]);
775 cpu_functioncall_trace(cpu, cpu->pc);
776 quick_pc_to_pointers(cpu);
777 instr(restore)(cpu, ic);
778 } else
779 cpu->delay_slot = NOT_DELAYED;
780 }
781
782
783 /*
784 * set: Set a register to a value (e.g. sethi).
785 *
786 * arg[0] = ptr to rd
787 * arg[1] = value (uint32_t)
788 */
789 X(set)
790 {
791 reg(ic->arg[0]) = (uint32_t)ic->arg[1];
792 }
793
794
795 /*
796 * Computational/arithmetic instructions:
797 *
798 * arg[0] = ptr to rs1
799 * arg[1] = ptr to rs2 or an immediate value (int32_t)
800 * arg[2] = ptr to rd
801 */
802 X(add) { reg(ic->arg[2]) = reg(ic->arg[0]) + reg(ic->arg[1]); }
803 X(add_imm) { reg(ic->arg[2]) = reg(ic->arg[0]) + (int32_t)ic->arg[1]; }
804 X(and) { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
805 X(and_imm) { reg(ic->arg[2]) = reg(ic->arg[0]) & (int32_t)ic->arg[1]; }
806 X(andn) { reg(ic->arg[2]) = reg(ic->arg[0]) & ~reg(ic->arg[1]); }
807 X(andn_imm) { reg(ic->arg[2]) = reg(ic->arg[0]) & ~(int32_t)ic->arg[1]; }
808 X(or) { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
809 X(or_imm) { reg(ic->arg[2]) = reg(ic->arg[0]) | (int32_t)ic->arg[1]; }
810 X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
811 X(xor_imm) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ (int32_t)ic->arg[1]; }
812 X(sub) { reg(ic->arg[2]) = reg(ic->arg[0]) - reg(ic->arg[1]); }
813 X(sub_imm) { reg(ic->arg[2]) = reg(ic->arg[0]) - (int32_t)ic->arg[1]; }
814
815 X(sll) { reg(ic->arg[2]) = (uint32_t)reg(ic->arg[0]) <<
816 (reg(ic->arg[1]) & 31); }
817 X(sllx) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) <<
818 (reg(ic->arg[1]) & 63); }
819 X(sll_imm) { reg(ic->arg[2]) = (uint32_t)reg(ic->arg[0]) << ic->arg[1]; }
820 X(sllx_imm) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) << ic->arg[1]; }
821
822 X(srl) { reg(ic->arg[2]) = (uint32_t)reg(ic->arg[0]) >>
823 (reg(ic->arg[1]) & 31); }
824 X(srlx) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) >>
825 (reg(ic->arg[1]) & 63); }
826 X(srl_imm) { reg(ic->arg[2]) = (uint32_t)reg(ic->arg[0]) >> ic->arg[1]; }
827 X(srlx_imm) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) >> ic->arg[1]; }
828
829 X(sra) { reg(ic->arg[2]) = (int32_t)reg(ic->arg[0]) >>
830 (reg(ic->arg[1]) & 31); }
831 X(srax) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >>
832 (reg(ic->arg[1]) & 63); }
833 X(sra_imm) { reg(ic->arg[2]) = (int32_t)reg(ic->arg[0]) >> ic->arg[1]; }
834 X(srax_imm) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> ic->arg[1]; }
835
836 X(udiv)
837 {
838 uint64_t z = (cpu->cd.sparc.y << 32) | (uint32_t)reg(ic->arg[0]);
839 z /= (uint32_t)reg(ic->arg[1]);
840 if (z > 0xffffffff)
841 z = 0xffffffff;
842 reg(ic->arg[2]) = z;
843 }
844 X(udiv_imm)
845 {
846 uint64_t z = (cpu->cd.sparc.y << 32) | (uint32_t)reg(ic->arg[0]);
847 z /= (uint32_t)ic->arg[1];
848 if (z > 0xffffffff)
849 z = 0xffffffff;
850 reg(ic->arg[2]) = z;
851 }
852
853
854 /*
855 * Add with ccr update:
856 *
857 * arg[0] = ptr to rs1
858 * arg[1] = ptr to rs2 or an immediate value (int32_t)
859 * arg[2] = ptr to rd
860 */
861 int32_t sparc_addcc32(struct cpu *cpu, int32_t rs1, int32_t rs2);
862 #ifdef MODE32
863 int32_t sparc_addcc32(struct cpu *cpu, int32_t rs1, int32_t rs2)
864 #else
865 int64_t sparc_addcc64(struct cpu *cpu, int64_t rs1, int64_t rs2)
866 #endif
867 {
868 int cc = 0, sign1 = 0, sign2 = 0, signd = 0, mask = SPARC_CCR_ICC_MASK;
869 MODE_int_t rd = rs1 + rs2;
870 if (rd == 0)
871 cc = SPARC_CCR_Z;
872 else if (rd < 0)
873 cc = SPARC_CCR_N, signd = 1;
874 if (rs1 < 0)
875 sign1 = 1;
876 if (rs2 < 0)
877 sign2 = 1;
878 if (sign1 == sign2 && sign1 != signd)
879 cc |= SPARC_CCR_V;
880 /* TODO: SPARC_CCR_C */
881 #ifndef MODE32
882 mask <<= SPARC_CCR_XCC_SHIFT;
883 cc <<= SPARC_CCR_XCC_SHIFT;
884 #endif
885 cpu->cd.sparc.ccr &= ~mask;
886 cpu->cd.sparc.ccr |= cc;
887 return rd;
888 }
889 X(addcc)
890 {
891 /* Like add, but updates the ccr, and does both 32-bit and
892 64-bit comparison at the same time. */
893 MODE_int_t rs1 = reg(ic->arg[0]), rs2 = reg(ic->arg[1]), rd;
894 rd = sparc_addcc32(cpu, rs1, rs2);
895 #ifndef MODE32
896 rd = sparc_addcc64(cpu, rs1, rs2);
897 #endif
898 reg(ic->arg[2]) = rd;
899 }
900 X(addcc_imm)
901 {
902 MODE_int_t rs1 = reg(ic->arg[0]), rs2 = (int32_t)ic->arg[1], rd;
903 rd = sparc_addcc32(cpu, rs1, rs2);
904 #ifndef MODE32
905 rd = sparc_addcc64(cpu, rs1, rs2);
906 #endif
907 reg(ic->arg[2]) = rd;
908 }
909
910
911 /*
912 * And with ccr update:
913 *
914 * arg[0] = ptr to rs1
915 * arg[1] = ptr to rs2 or an immediate value (int32_t)
916 * arg[2] = ptr to rd
917 */
918 int32_t sparc_andcc32(struct cpu *cpu, int32_t rs1, int32_t rs2);
919 #ifdef MODE32
920 int32_t sparc_andcc32(struct cpu *cpu, int32_t rs1, int32_t rs2)
921 #else
922 int64_t sparc_andcc64(struct cpu *cpu, int64_t rs1, int64_t rs2)
923 #endif
924 {
925 int cc = 0, mask = SPARC_CCR_ICC_MASK;
926 MODE_int_t rd = rs1 & rs2;
927 if (rd == 0)
928 cc = SPARC_CCR_Z;
929 else if (rd < 0)
930 cc = SPARC_CCR_N;
931 /* Note: SPARC_CCR_C and SPARC_CCR_V are always zero. */
932 #ifndef MODE32
933 mask <<= SPARC_CCR_XCC_SHIFT;
934 cc <<= SPARC_CCR_XCC_SHIFT;
935 #endif
936 cpu->cd.sparc.ccr &= ~mask;
937 cpu->cd.sparc.ccr |= cc;
938 return rd;
939 }
940 X(andcc)
941 {
942 /* Like and, but updates the ccr, and does both 32-bit and
943 64-bit comparison at the same time. */
944 MODE_int_t rs1 = reg(ic->arg[0]), rs2 = reg(ic->arg[1]), rd;
945 rd = sparc_andcc32(cpu, rs1, rs2);
946 #ifndef MODE32
947 rd = sparc_andcc64(cpu, rs1, rs2);
948 #endif
949 reg(ic->arg[2]) = rd;
950 }
951 X(andcc_imm)
952 {
953 MODE_int_t rs1 = reg(ic->arg[0]), rs2 = (int32_t)ic->arg[1], rd;
954 rd = sparc_andcc32(cpu, rs1, rs2);
955 #ifndef MODE32
956 rd = sparc_andcc64(cpu, rs1, rs2);
957 #endif
958 reg(ic->arg[2]) = rd;
959 }
960
961
962 /*
963 * Subtract with ccr update:
964 *
965 * arg[0] = ptr to rs1
966 * arg[1] = ptr to rs2 or an immediate value (int32_t)
967 * arg[2] = ptr to rd
968 */
969 int32_t sparc_subcc32(struct cpu *cpu, int32_t rs1, int32_t rs2);
970 #ifdef MODE32
971 int32_t sparc_subcc32(struct cpu *cpu, int32_t rs1, int32_t rs2)
972 #else
973 int64_t sparc_subcc64(struct cpu *cpu, int64_t rs1, int64_t rs2)
974 #endif
975 {
976 int cc = 0, sign1 = 0, sign2 = 0, signd = 0, mask = SPARC_CCR_ICC_MASK;
977 MODE_int_t rd = rs1 - rs2;
978 if (rd == 0)
979 cc = SPARC_CCR_Z;
980 else if (rd < 0)
981 cc = SPARC_CCR_N, signd = 1;
982 if (rs1 < 0)
983 sign1 = 1;
984 if (rs2 < 0)
985 sign2 = 1;
986 if (sign1 != sign2 && sign1 != signd)
987 cc |= SPARC_CCR_V;
988 /* TODO: SPARC_CCR_C */
989 #ifndef MODE32
990 mask <<= SPARC_CCR_XCC_SHIFT;
991 cc <<= SPARC_CCR_XCC_SHIFT;
992 #endif
993 cpu->cd.sparc.ccr &= ~mask;
994 cpu->cd.sparc.ccr |= cc;
995 return rd;
996 }
997 X(subcc)
998 {
999 /* Like sub, but updates the ccr, and does both 32-bit and
1000 64-bit comparison at the same time. */
1001 MODE_int_t rs1 = reg(ic->arg[0]), rs2 = reg(ic->arg[1]), rd;
1002 rd = sparc_subcc32(cpu, rs1, rs2);
1003 #ifndef MODE32
1004 rd = sparc_subcc64(cpu, rs1, rs2);
1005 #endif
1006 reg(ic->arg[2]) = rd;
1007 }
1008 X(subcc_imm)
1009 {
1010 MODE_int_t rs1 = reg(ic->arg[0]), rs2 = (int32_t)ic->arg[1], rd;
1011 rd = sparc_subcc32(cpu, rs1, rs2);
1012 #ifndef MODE32
1013 rd = sparc_subcc64(cpu, rs1, rs2);
1014 #endif
1015 reg(ic->arg[2]) = rd;
1016 }
1017
1018
1019 #include "tmp_sparc_loadstore.c"
1020
1021
1022 /*
1023 * rd: Read special register
1024 *
1025 * arg[2] = ptr to rd
1026 */
1027 X(rd_psr)
1028 {
1029 reg(ic->arg[2]) = cpu->cd.sparc.psr;
1030 }
1031
1032
1033 /*
1034 * rdpr: Read privileged register
1035 *
1036 * arg[2] = ptr to rd
1037 */
1038 X(rdpr_tba)
1039 {
1040 reg(ic->arg[2]) = cpu->cd.sparc.tba;
1041 }
1042 X(rdpr_ver)
1043 {
1044 reg(ic->arg[2]) = cpu->cd.sparc.ver;
1045 }
1046
1047
1048 /*
1049 * wrpr: Write to privileged register
1050 *
1051 * arg[0] = ptr to rs1
1052 * arg[1] = ptr to rs2 or an immediate value (int32_t)
1053 */
1054 X(wrpr_tick)
1055 {
1056 cpu->cd.sparc.tick = (uint32_t) (reg(ic->arg[0]) ^ reg(ic->arg[1]));
1057 }
1058 X(wrpr_tick_imm)
1059 {
1060 cpu->cd.sparc.tick = (uint32_t) (reg(ic->arg[0]) ^ (int32_t)ic->arg[1]);
1061 }
1062 X(wrpr_pil)
1063 {
1064 cpu->cd.sparc.pil = (reg(ic->arg[0]) ^ reg(ic->arg[1]))
1065 & SPARC_PIL_MASK;
1066 }
1067 X(wrpr_pil_imm)
1068 {
1069 cpu->cd.sparc.pil = (reg(ic->arg[0]) ^ (int32_t)ic->arg[1])
1070 & SPARC_PIL_MASK;
1071 }
1072 X(wrpr_pstate)
1073 {
1074 sparc_update_pstate(cpu, reg(ic->arg[0]) ^ reg(ic->arg[1]));
1075 }
1076 X(wrpr_pstate_imm)
1077 {
1078 sparc_update_pstate(cpu, reg(ic->arg[0]) ^ (int32_t)ic->arg[1]);
1079 }
1080
1081
1082 /*****************************************************************************/
1083
1084
1085 X(end_of_page)
1086 {
1087 /* Update the PC: (offset 0, but on the next page) */
1088 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1) <<
1089 SPARC_INSTR_ALIGNMENT_SHIFT);
1090 cpu->pc += (SPARC_IC_ENTRIES_PER_PAGE <<
1091 SPARC_INSTR_ALIGNMENT_SHIFT);
1092
1093 /* Find the new physical page and update the translation pointers: */
1094 quick_pc_to_pointers(cpu);
1095
1096 /* end_of_page doesn't count as an executed instruction: */
1097 cpu->n_translated_instrs --;
1098 }
1099
1100
1101 X(end_of_page2)
1102 {
1103 /* Synchronize PC on the _second_ instruction on the next page: */
1104 int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
1105 / sizeof(struct sparc_instr_call);
1106 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
1107 << SPARC_INSTR_ALIGNMENT_SHIFT);
1108 cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
1109
1110 /* This doesn't count as an executed instruction. */
1111 cpu->n_translated_instrs --;
1112
1113 quick_pc_to_pointers(cpu);
1114
1115 if (cpu->delay_slot == NOT_DELAYED)
1116 return;
1117
1118 fatal("end_of_page2: fatal error, we're in a delay slot\n");
1119 exit(1);
1120 }
1121
1122
1123 /*****************************************************************************/
1124
1125
1126 /*
1127 * sparc_instr_to_be_translated():
1128 *
1129 * Translate an instruction word into a sparc_instr_call. ic is filled in with
1130 * valid data for the translated instruction, or a "nothing" instruction if
1131 * there was a translation failure. The newly translated instruction is then
1132 * executed.
1133 */
1134 X(to_be_translated)
1135 {
1136 MODE_uint_t addr;
1137 int low_pc, in_crosspage_delayslot = 0;
1138 uint32_t iword;
1139 unsigned char *page;
1140 unsigned char ib[4];
1141 int main_opcode, op2, rd, rs1, rs2, btype, asi, cc, p, use_imm, x64 = 0;
1142 int store, signedness, size;
1143 int32_t tmpi32, siconst;
1144 /* void (*samepage_function)(struct cpu *, struct sparc_instr_call *);*/
1145
1146 /* Figure out the (virtual) address of the instruction: */
1147 low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
1148 / sizeof(struct sparc_instr_call);
1149
1150 /* Special case for branch with delayslot on the next page: */
1151 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
1152 /* fatal("[ delay-slot translation across page "
1153 "boundary ]\n"); */
1154 in_crosspage_delayslot = 1;
1155 }
1156
1157 addr = cpu->pc & ~((SPARC_IC_ENTRIES_PER_PAGE-1)
1158 << SPARC_INSTR_ALIGNMENT_SHIFT);
1159 addr += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
1160 cpu->pc = addr;
1161 addr &= ~((1 << SPARC_INSTR_ALIGNMENT_SHIFT) - 1);
1162
1163 /* Read the instruction word from memory: */
1164 #ifdef MODE32
1165 page = cpu->cd.sparc.host_load[addr >> 12];
1166 #else
1167 {
1168 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1169 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1170 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1171 uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
1172 uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1173 uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
1174 DYNTRANS_L3N)) & mask3;
1175 struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.sparc.l1_64[x1];
1176 struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
1177 page = l3->host_load[x3];
1178 }
1179 #endif
1180
1181 if (page != NULL) {
1182 /* fatal("TRANSLATION HIT!\n"); */
1183 memcpy(ib, page + (addr & 0xffc), sizeof(ib));
1184 } else {
1185 /* fatal("TRANSLATION MISS!\n"); */
1186 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
1187 sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
1188 fatal("to_be_translated(): "
1189 "read failed: TODO\n");
1190 goto bad;
1191 }
1192 }
1193
1194 /* SPARC instruction words are always big-endian. Convert
1195 to host order: */
1196 iword = BE32_TO_HOST( *((uint32_t *)&ib[0]) );
1197
1198
1199 #define DYNTRANS_TO_BE_TRANSLATED_HEAD
1200 #include "cpu_dyntrans.c"
1201 #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
1202
1203
1204 /*
1205 * Translate the instruction:
1206 */
1207
1208 main_opcode = iword >> 30;
1209 rd = (iword >> 25) & 31;
1210 btype = rd & (N_SPARC_BRANCH_TYPES - 1);
1211 rs1 = (iword >> 14) & 31;
1212 use_imm = (iword >> 13) & 1;
1213 asi = (iword >> 5) & 0xff;
1214 rs2 = iword & 31;
1215 siconst = (int16_t)((iword & 0x1fff) << 3) >> 3;
1216 op2 = (main_opcode == 0)? ((iword >> 22) & 7) : ((iword >> 19) & 0x3f);
1217 cc = (iword >> 20) & 3;
1218 p = (iword >> 19) & 1;
1219
1220 switch (main_opcode) {
1221
1222 case 0: switch (op2) {
1223
1224 case 1: /* branch (icc or xcc) */
1225 tmpi32 = (iword << 13);
1226 tmpi32 >>= 11;
1227 ic->arg[0] = (int32_t)tmpi32 + (addr & 0xffc);
1228 /* rd contains the annul bit concatenated with 4 bits
1229 of condition code. cc=0 for icc, 2 for xcc: */
1230 /* TODO: samepage */
1231 switch (rd + (cc << 5)) {
1232 case 0x01: ic->f = instr(be); break;
1233 case 0x02: ic->f = instr(ble); break;
1234 case 0x03: ic->f = instr(bl); break;
1235 case 0x08: ic->f = instr(ba); break;
1236 case 0x09: ic->f = instr(bne); break;
1237 case 0x0a: ic->f = instr(bg); break;
1238 case 0x0b: ic->f = instr(bge); break;
1239 case 0x19: ic->f = instr(bne_a); break;
1240 case 0x41: ic->f = instr(be_xcc); break;
1241 case 0x42: ic->f = instr(ble_xcc);break;
1242 case 0x43: ic->f = instr(bl_xcc); break;
1243 case 0x48: ic->f = instr(ba); break;
1244 case 0x4a: ic->f = instr(bg_xcc); break;
1245 case 0x4b: ic->f = instr(bge_xcc);break;
1246 default:fatal("Unimplemented branch, 0x%x\n",
1247 rd + (cc<<5));
1248 goto bad;
1249 }
1250 break;
1251
1252 case 2: /* branch (32-bit integer comparison) */
1253 tmpi32 = (iword << 10);
1254 tmpi32 >>= 8;
1255 ic->arg[0] = (int32_t)tmpi32 + (addr & 0xffc);
1256 /* rd contains the annul bit concatenated with 4 bits
1257 of condition code: */
1258 /* TODO: samepage */
1259 switch (rd) {
1260 case 0x01: ic->f = instr(be); break;
1261 case 0x03: ic->f = instr(bl); break;
1262 case 0x08: ic->f = instr(ba); break;
1263 case 0x09: ic->f = instr(bne); break;
1264 case 0x0b: ic->f = instr(bge); break;
1265 default:fatal("Unimplemented branch rd=%i\n", rd);
1266 goto bad;
1267 }
1268 break;
1269
1270 case 3: /* branch on register, 64-bit integer comparison */
1271 tmpi32 = ((iword & 0x300000) >> 6) | (iword & 0x3fff);
1272 tmpi32 <<= 16;
1273 tmpi32 >>= 14;
1274 ic->arg[0] = (int32_t)tmpi32 + (addr & 0xffc);
1275 ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs1];
1276 /* TODO: samepage */
1277 switch (btype) {
1278 case 0x05: ic->f = instr(brnz); break;
1279 default:fatal("Unimplemented branch 0x%x\n", rd);
1280 goto bad;
1281 }
1282 break;
1283
1284 case 4: /* sethi */
1285 ic->arg[0] = (size_t)&cpu->cd.sparc.r[rd];
1286 ic->arg[1] = (iword & 0x3fffff) << 10;
1287 ic->f = instr(set);
1288 if (rd == SPARC_ZEROREG)
1289 ic->f = instr(nop);
1290 break;
1291
1292 default:fatal("TODO: unimplemented op2=%i for main "
1293 "opcode %i\n", op2, main_opcode);
1294 goto bad;
1295 }
1296 break;
1297
1298 case 1: /* call and link */
1299 tmpi32 = (iword << 2);
1300 ic->arg[0] = (int32_t)tmpi32;
1301 ic->arg[1] = addr & 0xffc;
1302 if (cpu->machine->show_trace_tree)
1303 ic->f = instr(call_trace);
1304 else
1305 ic->f = instr(call);
1306 /* TODO: samepage */
1307 break;
1308
1309 case 2: switch (op2) {
1310
1311 case 0: /* add */
1312 case 1: /* and */
1313 case 2: /* or */
1314 case 3: /* xor */
1315 case 4: /* sub */
1316 case 5: /* andn */
1317 case 14:/* udiv */
1318 case 16:/* addcc */
1319 case 17:/* andcc */
1320 case 20:/* subcc (cmp) */
1321 case 37:/* sll */
1322 case 38:/* srl */
1323 case 39:/* sra */
1324 case 60:/* save */
1325 ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1];
1326 ic->f = NULL;
1327 if (use_imm) {
1328 ic->arg[1] = siconst;
1329 switch (op2) {
1330 case 0: ic->f = instr(add_imm); break;
1331 case 1: ic->f = instr(and_imm); break;
1332 case 2: ic->f = instr(or_imm); break;
1333 case 3: ic->f = instr(xor_imm); break;
1334 case 4: ic->f = instr(sub_imm); break;
1335 case 5: ic->f = instr(andn_imm); break;
1336 case 14:ic->f = instr(udiv_imm); break;
1337 case 16:ic->f = instr(addcc_imm); break;
1338 case 17:ic->f = instr(andcc_imm); break;
1339 case 20:ic->f = instr(subcc_imm); break;
1340 case 37:if (siconst & 0x1000) {
1341 ic->f = instr(sllx_imm);
1342 ic->arg[1] &= 63;
1343 x64 = 1;
1344 } else {
1345 ic->f = instr(sll_imm);
1346 ic->arg[1] &= 31;
1347 }
1348 break;
1349 case 38:if (siconst & 0x1000) {
1350 ic->f = instr(srlx_imm);
1351 ic->arg[1] &= 63;
1352 x64 = 1;
1353 } else {
1354 ic->f = instr(srl_imm);
1355 ic->arg[1] &= 31;
1356 }
1357 break;
1358 case 39:if (siconst & 0x1000) {
1359 ic->f = instr(srax_imm);
1360 ic->arg[1] &= 63;
1361 x64 = 1;
1362 } else {
1363 ic->f = instr(sra_imm);
1364 ic->arg[1] &= 31;
1365 }
1366 break;
1367 case 60:switch (cpu->cd.sparc.cpu_type.v) {
1368 case 9: ic->f = instr(save_v9_imm);
1369 break;
1370 default:fatal("only for v9 so far\n");
1371 goto bad;
1372 }
1373 }
1374 } else {
1375 ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2];
1376 switch (op2) {
1377 case 0: ic->f = instr(add); break;
1378 case 1: ic->f = instr(and); break;
1379 case 2: ic->f = instr(or); break;
1380 case 3: ic->f = instr(xor); break;
1381 case 4: ic->f = instr(sub); break;
1382 case 5: ic->f = instr(andn); break;
1383 case 14:ic->f = instr(udiv); break;
1384 case 16:ic->f = instr(addcc); break;
1385 case 17:ic->f = instr(andcc); break;
1386 case 20:ic->f = instr(subcc); break;
1387 case 37:if (siconst & 0x1000) {
1388 ic->f = instr(sllx);
1389 x64 = 1;
1390 } else
1391 ic->f = instr(sll);
1392 break;
1393 case 38:if (siconst & 0x1000) {
1394 ic->f = instr(srlx);
1395 x64 = 1;
1396 } else
1397 ic->f = instr(srl);
1398 break;
1399 case 39:if (siconst & 0x1000) {
1400 ic->f = instr(srax);
1401 x64 = 1;
1402 } else
1403 ic->f = instr(sra);
1404 break;
1405 }
1406 }
1407 if (ic->f == NULL) {
1408 fatal("TODO: Unimplemented instruction "
1409 "(possibly missed use_imm impl.)\n");
1410 goto bad;
1411 }
1412 ic->arg[2] = (size_t)&cpu->cd.sparc.r[rd];
1413 if (rd == SPARC_ZEROREG) {
1414 /*
1415 * Some opcodes should write to the scratch
1416 * register instead of becoming NOPs, when
1417 * rd is the zero register.
1418 *
1419 * Any opcode which updates the condition
1420 * codes, or anything which changes register
1421 * windows.
1422 */
1423 switch (op2) {
1424 case 16:/* addcc */
1425 case 17:/* andcc */
1426 case 20:/* subcc */
1427 case 60:/* save */
1428 ic->arg[2] = (size_t)
1429 &cpu->cd.sparc.scratch;
1430 break;
1431 default:ic->f = instr(nop);
1432 }
1433 }
1434 break;
1435
1436 case 41:/* rd %psr,%gpr on pre-sparcv9 */
1437 if (cpu->is_32bit) {
1438 ic->f = instr(rd_psr);
1439 ic->arg[2] = (size_t)&cpu->cd.sparc.r[rd];
1440 if (rd == SPARC_ZEROREG)
1441 ic->f = instr(nop);
1442 } else {
1443 fatal("opcode 2,41 not yet implemented"
1444 " for 64-bit cpus\n");
1445 goto bad;
1446 }
1447 break;
1448
1449 case 42:/* rdpr on sparcv9 */
1450 if (cpu->is_32bit) {
1451 fatal("opcode 2,42 not yet implemented"
1452 " for 32-bit cpus\n");
1453 goto bad;
1454 }
1455 ic->arg[2] = (size_t)&cpu->cd.sparc.r[rd];
1456 if (rd == SPARC_ZEROREG)
1457 ic->f = instr(nop);
1458 switch (rs1) {
1459 case 5: ic->f = instr(rdpr_tba); break;
1460 case 31: ic->f = instr(rdpr_ver); break;
1461 default:fatal("Unimplemented rs1=%i\n", rs1);
1462 goto bad;
1463 }
1464 break;
1465
1466 case 48:/* wr (Note: works as xor) */
1467 ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1];
1468 if (use_imm) {
1469 ic->arg[1] = siconst;
1470 ic->f = instr(xor_imm);
1471 } else {
1472 ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2];
1473 ic->f = instr(xor);
1474 }
1475 ic->arg[2] = (size_t) NULL;
1476 switch (rd) {
1477 case 0: ic->arg[2] = (size_t)&cpu->cd.sparc.y;
1478 break;
1479 case 6: ic->arg[2] = (size_t)&cpu->cd.sparc.fprs;
1480 break;
1481 case 0x17:
1482 ic->arg[2] = (size_t)&cpu->cd.sparc.tick_cmpr;
1483 break;
1484 }
1485 if (ic->arg[2] == (size_t)NULL) {
1486 fatal("TODO: Unimplemented wr instruction, "
1487 "rd = 0x%02x\n", rd);
1488 goto bad;
1489 }
1490 break;
1491
1492 case 50:/* wrpr (Note: works as xor) */
1493 ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1];
1494 ic->f = NULL;
1495 if (use_imm) {
1496 ic->arg[1] = siconst;
1497 switch (rd) {
1498 case 4: ic->f = instr(wrpr_tick_imm); break;
1499 case 6: ic->f = instr(wrpr_pstate_imm); break;
1500 case 8: ic->f = instr(wrpr_pil_imm); break;
1501 }
1502 } else {
1503 ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2];
1504 switch (rd) {
1505 case 4: ic->f = instr(wrpr_tick); break;
1506 case 6: ic->f = instr(wrpr_pstate); break;
1507 case 8: ic->f = instr(wrpr_pil); break;
1508 }
1509 }
1510 if (ic->f == NULL) {
1511 fatal("TODO: Unimplemented wrpr instruction,"
1512 " rd = 0x%02x\n", rd);
1513 goto bad;
1514 }
1515 break;
1516
1517 case 56:/* jump and link */
1518 ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1];
1519 ic->arg[2] = (size_t)&cpu->cd.sparc.r[rd];
1520 if (rd == SPARC_ZEROREG)
1521 ic->arg[2] = (size_t)&cpu->cd.sparc.scratch;
1522
1523 if (use_imm) {
1524 ic->arg[1] = siconst;
1525 if (rd == SPARC_ZEROREG)
1526 ic->f = instr(jmpl_imm_no_rd);
1527 else
1528 ic->f = instr(jmpl_imm);
1529 } else {
1530 ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2];
1531 if (rd == SPARC_ZEROREG)
1532 ic->f = instr(jmpl_reg_no_rd);
1533 else
1534 ic->f = instr(jmpl_reg);
1535 }
1536
1537 /* special trace case: */
1538 if (cpu->machine->show_trace_tree) {
1539 if (iword == 0x81c3e008)
1540 ic->f = instr(retl_trace);
1541 else {
1542 if (use_imm)
1543 ic->f = instr(jmpl_imm_trace);
1544 else
1545 ic->f = instr(jmpl_reg_trace);
1546 }
1547 }
1548 break;
1549
1550 case 57:/* return */
1551 ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1];
1552
1553 if (use_imm) {
1554 ic->arg[1] = siconst;
1555 ic->f = instr(return_imm);
1556 } else {
1557 ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2];
1558 ic->f = instr(return_reg);
1559 }
1560
1561 /* special trace case: */
1562 if (cpu->machine->show_trace_tree) {
1563 if (use_imm)
1564 ic->f = instr(return_imm_trace);
1565 else
1566 ic->f = instr(return_reg_trace);
1567 }
1568 break;
1569
1570 default:fatal("TODO: unimplemented op2=%i for main "
1571 "opcode %i\n", op2, main_opcode);
1572 goto bad;
1573 }
1574 break;
1575
1576 case 3: switch (op2) {
1577
1578 case 0:/* lduw */
1579 case 1:/* ldub */
1580 case 2:/* lduh */
1581 case 4:/* st(w) */
1582 case 5:/* stb */
1583 case 6:/* sth */
1584 case 8:/* ldsw */
1585 case 9:/* ldsb */
1586 case 10:/* ldsh */
1587 case 11:/* ldx */
1588 case 14:/* stx */
1589 store = 1; signedness = 0; size = 3;
1590 switch (op2) {
1591 case 0: /* lduw */ store=0; size=2; break;
1592 case 1: /* ldub */ store=0; size=0; break;
1593 case 2: /* lduh */ store=0; size=1; break;
1594 case 4: /* st */ size = 2; break;
1595 case 5: /* stb */ size = 0; break;
1596 case 6: /* sth */ size = 1; break;
1597 case 8: /* ldsw */ store=0; size=2; signedness=1;
1598 break;
1599 case 9: /* ldsb */ store=0; size=0; signedness=1;
1600 break;
1601 case 10: /* ldsh */ store=0; size=1; signedness=1;
1602 break;
1603 case 11: /* ldx */ store=0; break;
1604 case 14: /* stx */ break;
1605 }
1606 ic->f =
1607 #ifdef MODE32
1608 sparc32_loadstore
1609 #else
1610 sparc_loadstore
1611 #endif
1612 [ use_imm*16 + store*8 + size*2 + signedness ];
1613
1614 ic->arg[0] = (size_t)&cpu->cd.sparc.r[rd];
1615 ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs1];
1616 if (use_imm)
1617 ic->arg[2] = siconst;
1618 else
1619 ic->arg[2] = (size_t)&cpu->cd.sparc.r[rs2];
1620
1621 if (!store && rd == SPARC_ZEROREG)
1622 ic->arg[0] = (size_t)&cpu->cd.sparc.scratch;
1623
1624 break;
1625
1626 default:fatal("TODO: unimplemented op2=%i for main "
1627 "opcode %i\n", op2, main_opcode);
1628 goto bad;
1629 }
1630 break;
1631
1632 }
1633
1634
1635 if (x64 && cpu->is_32bit) {
1636 fatal("TODO: 64-bit instr on 32-bit cpu\n");
1637 goto bad;
1638 }
1639
1640
1641 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
1642 #include "cpu_dyntrans.c"
1643 #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
1644 }
1645

  ViewVC Help
Powered by ViewVC 1.1.26