/[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 32 - (show annotations)
Mon Oct 8 16:20:58 2007 UTC (13 years ago) by dpavlin
File MIME type: text/plain
File size: 45218 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1421 2006/11/06 05:32:37 debug Exp $
20060816	Adding a framework for emulated/virtual timers (src/timer.c),
		using only setitimer().
		Rewriting the mc146818 to use the new timer framework.
20060817	Adding a call to gettimeofday() every now and then (once every
		second, at the moment) to resynch the timer if it drifts.
		Beginning to convert the ISA timer interrupt mechanism (8253
		and 8259) to use the new timer framework.
		Removing the -I command line option.
20060819	Adding the -I command line option again, with new semantics.
		Working on Footbridge timer interrupts; NetBSD/NetWinder and
		NetBSD/CATS now run at correct speed, but unfortunately with
		HUGE delays during bootup.
20060821	Some minor m68k updates. Adding the first instruction: nop. :)
		Minor Alpha emulation updates.
20060822	Adding a FreeBSD development specific YAMON environment
		variable ("khz") (as suggested by Bruce M. Simpson).
		Moving YAMON environment variable initialization from
		machine_evbmips.c into promemul/yamon.c, and adding some more
		variables.
		Continuing on the LCA PCI bus controller (for Alpha machines).
20060823	Continuing on the timer stuff: experimenting with MIPS count/
		compare interrupts connected to the timer framework.
20060825	Adding bogus SCSI commands 0x51 (SCSICDROM_READ_DISCINFO) and
		0x52 (SCSICDROM_READ_TRACKINFO) to the SCSI emulation layer,
		to allow NetBSD/pmax 4.0_BETA to be installed from CDROM.
		Minor updates to the LCA PCI controller.
20060827	Implementing a CHIP8 cpu mode, and a corresponding CHIP8
		machine, for fun. Disassembly support for all instructions,
		and most of the common instructions have been implemented: mvi,
		mov_imm, add_imm, jmp, rand, cls, sprite, skeq_imm, jsr,
		skne_imm, bcd, rts, ldr, str, mov, or, and, xor, add, sub,
		font, ssound, sdelay, gdelay, bogus skup/skpr, skeq, skne.
20060828	Beginning to convert the CHIP8 cpu in the CHIP8 machine to a
		(more correct) RCA 180x cpu. (Disassembly for all 1802
		instructions has been implemented, but no execution yet, and
		no 1805 extended instructions.)
20060829	Minor Alpha emulation updates.
20060830	Beginning to experiment a little with PCI IDE for SGI O2.
		Fixing the cursor key mappings for MobilePro 770 emulation.
		Fixing the LK201 warning caused by recent NetBSD/pmax.
		The MIPS R41xx standby, suspend, and hibernate instructions now
		behave like the RM52xx/MIPS32/MIPS64 wait instruction.
		Fixing dev_wdc so it calculates correct (64-bit) offsets before
		giving them to diskimage_access().
20060831	Continuing on Alpha emulation (OSF1 PALcode).
20060901	Minor Alpha updates; beginning on virtual memory pagetables.
		Removed the limit for max nr of devices (in preparation for
		allowing devices' base addresses to be changed during runtime).
		Adding a hack for MIPS [d]mfc0 select 0 (except the count
		register), so that the coproc register is simply copied.
		The MIPS suspend instruction now exits the emulator, instead
		of being treated as a wait instruction (this causes NetBSD/
		hpcmips to get correct 'halt' behavior).
		The VR41xx RTC now returns correct time.
		Connecting the VR41xx timer to the timer framework (fixed at
		128 Hz, for now).
		Continuing on SPARC emulation, adding more instructions:
		restore, ba_xcc, ble. The rectangle drawing demo works :)
		Removing the last traces of the old ENABLE_CACHE_EMULATION
		MIPS stuff (not usable with dyntrans anyway).
20060902	Splitting up src/net.c into several smaller files in its own
		subdirectory (src/net/).
20060903	Cleanup of the files in src/net/, to make them less ugly.
20060904	Continuing on the 'settings' subsystem.
		Minor progress on the SPARC emulation mode.
20060905	Cleanup of various things, and connecting the settings
		infrastructure to various subsystems (emul, machine, cpu, etc).
		Changing the lk201 mouse update routine to not rely on any
		emulated hardware framebuffer cursor coordinates, but instead
		always do (semi-usable) relative movements.
20060906	Continuing on the lk201 mouse stuff. Mouse behaviour with
		multiple framebuffers (which was working in Ultrix) is now
		semi-broken (but it still works, in a way).
		Moving the documentation about networking into its own file
		(networking.html), and refreshing it a bit. Adding an example
		of how to use ethernet frame direct-access (udp_snoop).
20060907	Continuing on the settings infrastructure.
20060908	Minor updates to SH emulation: for 32-bit emulation: delay
		slots and the 'jsr @Rn' instruction. I'm putting 64-bit SH5 on
		ice, for now.
20060909-10	Implementing some more 32-bit SH instructions. Removing the
		64-bit mode completely. Enough has now been implemented to run
		the rectangle drawing demo. :-)
20060912	Adding more SH instructions.
20060916	Continuing on SH emulation (some more instructions: div0u,
		div1, rotcl/rotcr, more mov instructions, dt, braf, sets, sett,
		tst_imm, dmuls.l, subc, ldc_rm_vbr, movt, clrt, clrs, clrmac).
		Continuing on the settings subsystem (beginning on reading/
		writing settings, removing bugs, and connecting more cpus to
		the framework).
20060919	More work on SH emulation; adding an ldc banked instruction,
		and attaching a 640x480 framebuffer to the Dreamcast machine
		mode (NetBSD/dreamcast prints the NetBSD copyright banner :-),
		and then panics).
20060920	Continuing on the settings subsystem.
20060921	Fixing the Footbridge timer stuff so that NetBSD/cats and
		NetBSD/netwinder boot up without the delays.
20060922	Temporarily hardcoding MIPS timer interrupt to 100 Hz. With
		'wait' support disabled, NetBSD/malta and Linux/malta run at
		correct speed.
20060923	Connecting dev_gt to the timer framework, so that NetBSD/cobalt
		runs at correct speed.
		Moving SH4-specific memory mapped registers into its own
		device (dev_sh4.c).
		Running with -N now prints "idling" instead of bogus nr of
		instrs/second (which isn't valid anyway) while idling.
20060924	Algor emulation should now run at correct speed.
		Adding disassembly support for some MIPS64 revision 2
		instructions: ext, dext, dextm, dextu.
20060926	The timer framework now works also when the MIPS wait
		instruction is used.
20060928	Re-implementing checks for coprocessor availability for MIPS
		cop0 instructions. (Thanks to Carl van Schaik for noticing the
		lack of cop0 availability checks.)
20060929	Implementing an instruction combination hack which treats
		NetBSD/pmax' idle loop as a wait-like instruction.
20060930	The ENTRYHI_R_MASK was missing in (at least) memory_mips_v2p.c,
		causing TLB lookups to sometimes succeed when they should have
		failed. (A big thank you to Juli Mallett for noticing the
		problem.)
		Adding disassembly support for more MIPS64 revision 2 opcodes
		(seb, seh, wsbh, jalr.hb, jr.hb, synci, ins, dins, dinsu,
		dinsm, dsbh, dshd, ror, dror, rorv, drorv, dror32). Also
		implementing seb, seh, dsbh, dshd, and wsbh.
		Implementing an instruction combination hack for Linux/pmax'
		idle loop, similar to the NetBSD/pmax case.
20061001	Changing the NetBSD/sgimips install instructions to extract
		files from an iso image, instead of downloading them via ftp.
20061002	More-than-31-bit userland addresses in memory_mips_v2p.c were
		not actually working; applying a fix from Carl van Schaik to
		enable them to work + making some other updates (adding kuseg
		support).
		Fixing hpcmips (vr41xx) timer initialization.
		Experimenting with O(n)->O(1) reduction in the MIPS TLB lookup
		loop. Seems to work both for R3000 and non-R3000.
20061003	Continuing a little on SH emulation (adding more control
		registers; mini-cleanup of memory_sh.c).
20061004	Beginning on a dev_rtc, a clock/timer device for the test
		machines; also adding a demo, and some documentation.
		Fixing a bug in SH "mov.w @(disp,pc),Rn" (the result wasn't
		sign-extended), and adding the addc and ldtlb instructions.
20061005	Contining on SH emulation: virtual to physical address
		translation, and a skeleton exception mechanism.
20061006	Adding more SH instructions (various loads and stores, rte,
		negc, muls.w, various privileged register-move instructions).
20061007	More SH instructions: various move instructions, trapa, div0s,
		float, fdiv, ftrc.
		Continuing on dev_rtc; removing the rtc demo.
20061008	Adding a dummy Dreamcast PROM module. (Homebrew Dreamcast
		programs using KOS libs need this.)
		Adding more SH instructions: "stc vbr,rn", rotl, rotr, fsca,
		fmul, fadd, various floating-point moves, etc. A 256-byte
		demo for Dreamcast runs :-)
20061012	Adding the SH "lds Rm,pr" and bsr instructions.
20061013	More SH instructions: "sts fpscr,rn", tas.b, and some more
		floating point instructions, cmp/str, and more moves.
		Adding a dummy dev_pvr (Dreamcast graphics controller).
20061014	Generalizing the expression evaluator (used in the built-in
		debugger) to support parentheses and +-*/%^&|.
20061015	Removing the experimental tlb index hint code in
		mips_memory_v2p.c, since it didn't really have any effect.
20061017	Minor SH updates; adding the "sts pr,Rn", fcmp/gt, fneg,
		frchg, and some other instructions. Fixing missing sign-
		extension in an 8-bit load instruction.
20061019	Adding a simple dev_dreamcast_rtc.
		Implementing memory-mapped access to the SH ITLB/UTLB arrays.
20061021	Continuing on various SH and Dreamcast things: sh4 timers,
		debug messages for dev_pvr, fixing some virtual address
		translation bugs, adding the bsrf instruction.
		The NetBSD/dreamcast GENERIC_MD kernel now reaches userland :)
		Adding a dummy dev_dreamcast_asic.c (not really useful yet).
		Implementing simple support for Store Queues.
		Beginning on the PVR Tile Accelerator.
20061022	Generalizing the PVR framebuffer to support off-screen drawing,
		multiple bit-depths, etc. (A small speed penalty, but most
		likely worth it.)
		Adding more SH instructions (mulu.w, fcmp/eq, fsub, fmac,
		fschg, and some more); correcting bugs in "fsca" and "float".
20061024	Adding the SH ftrv (matrix * vector) instruction. Marcus
		Comstedt's "tatest" example runs :) (wireframe only).
		Correcting disassembly for SH floating point instructions that
		use the xd* registers.
		Adding the SH fsts instruction.
		In memory_device_dyntrans_access(), only the currently used
		range is now invalidated, and not the entire device range.
20061025	Adding a dummy AVR32 cpu mode skeleton.
20061026	Various Dreamcast updates; beginning on a Maple bus controller.
20061027	Continuing on the Maple bus. A bogus Controller, Keyboard, and
		Mouse can now be detected by NetBSD and KOS homebrew programs.
		Cleaning up the SH4 Timer Management Unit, and beginning on
		SH4 interrupts.
		Implementing the Dreamcast SYSASIC.
20061028	Continuing on the SYSASIC.
		Adding the SH fsqrt instruction.
		memory_sh.c now actually scans the ITLB.
		Fixing a bug in dev_sh4.c, related to associative writes into
		the memory-mapped UTLB array. NetBSD/dreamcast now reaches
		userland stably, and prints the "Terminal type?" message :-]
		Implementing enough of the Dreamcast keyboard to make NetBSD
		accept it for input.
		Enabling SuperH for stable (non-development) builds.
		Adding NetBSD/dreamcast to the documentation, although it
		doesn't support root-on-nfs yet.
20061029	Changing usleep(1) calls in the debugger to to usleep(10000)
		(according to Brian Foley, this makes GXemul run better on
		MacOS X).
		Making the Maple "Controller" do something (enough to barely
		interact with dcircus.elf).
20061030-31	Some progress on the PVR. More test programs start running (but
		with strange output).
		Various other SH4-related updates.
20061102	Various Dreamcast and SH4 updates; more KOS demos run now.
20061104	Adding a skeleton dev_mb8696x.c (the Dreamcast's LAN adapter).
20061105	Continuing on the MB8696x; NetBSD/dreamcast detects it as mbe0.
		Testing for the release.

==============  RELEASE 0.4.3  ==============


1 /*
2 * Copyright (C) 2005-2006 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.25 2006/09/04 15:35: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