/[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 44 - (show annotations)
Mon Oct 8 16:22:56 2007 UTC (13 years, 3 months ago) by dpavlin
File MIME type: text/plain
File size: 45975 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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.29 2007/06/28 13:36:47 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 * flushw: Flush Register Windows
1024 */
1025 X(flushw)
1026 {
1027 /* flushw acts as a nop, if cansave = nwindows - 2: */
1028 if (cpu->cd.sparc.cansave == cpu->cd.sparc.cpu_type.nwindows - 2)
1029 return;
1030
1031 /* TODO */
1032 fatal("flushw: TODO: cansave = %i\n", cpu->cd.sparc.cansave);
1033 exit(1);
1034 }
1035
1036
1037 /*
1038 * rd: Read special register
1039 *
1040 * arg[2] = ptr to rd
1041 */
1042 X(rd_psr)
1043 {
1044 reg(ic->arg[2]) = cpu->cd.sparc.psr;
1045 }
1046
1047
1048 /*
1049 * rdpr: Read privileged register
1050 *
1051 * arg[2] = ptr to rd
1052 */
1053 X(rdpr_tba)
1054 {
1055 reg(ic->arg[2]) = cpu->cd.sparc.tba;
1056 }
1057 X(rdpr_ver)
1058 {
1059 reg(ic->arg[2]) = cpu->cd.sparc.ver;
1060 }
1061
1062
1063 /*
1064 * wrpr: Write to privileged register
1065 *
1066 * arg[0] = ptr to rs1
1067 * arg[1] = ptr to rs2 or an immediate value (int32_t)
1068 */
1069 X(wrpr_tick)
1070 {
1071 cpu->cd.sparc.tick = (uint32_t) (reg(ic->arg[0]) ^ reg(ic->arg[1]));
1072 }
1073 X(wrpr_tick_imm)
1074 {
1075 cpu->cd.sparc.tick = (uint32_t) (reg(ic->arg[0]) ^ (int32_t)ic->arg[1]);
1076 }
1077 X(wrpr_pil)
1078 {
1079 cpu->cd.sparc.pil = (reg(ic->arg[0]) ^ reg(ic->arg[1]))
1080 & SPARC_PIL_MASK;
1081 }
1082 X(wrpr_pil_imm)
1083 {
1084 cpu->cd.sparc.pil = (reg(ic->arg[0]) ^ (int32_t)ic->arg[1])
1085 & SPARC_PIL_MASK;
1086 }
1087 X(wrpr_pstate)
1088 {
1089 sparc_update_pstate(cpu, reg(ic->arg[0]) ^ reg(ic->arg[1]));
1090 }
1091 X(wrpr_pstate_imm)
1092 {
1093 sparc_update_pstate(cpu, reg(ic->arg[0]) ^ (int32_t)ic->arg[1]);
1094 }
1095 X(wrpr_cleanwin)
1096 {
1097 cpu->cd.sparc.cleanwin = (uint32_t) (reg(ic->arg[0]) ^ reg(ic->arg[1]));
1098 }
1099 X(wrpr_cleanwin_imm)
1100 {
1101 cpu->cd.sparc.cleanwin =
1102 (uint32_t) (reg(ic->arg[0]) ^ (int32_t)ic->arg[1]);
1103 }
1104
1105
1106 /*****************************************************************************/
1107
1108
1109 X(end_of_page)
1110 {
1111 /* Update the PC: (offset 0, but on the next page) */
1112 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1) <<
1113 SPARC_INSTR_ALIGNMENT_SHIFT);
1114 cpu->pc += (SPARC_IC_ENTRIES_PER_PAGE <<
1115 SPARC_INSTR_ALIGNMENT_SHIFT);
1116
1117 /* Find the new physical page and update the translation pointers: */
1118 quick_pc_to_pointers(cpu);
1119
1120 /* end_of_page doesn't count as an executed instruction: */
1121 cpu->n_translated_instrs --;
1122 }
1123
1124
1125 X(end_of_page2)
1126 {
1127 /* Synchronize PC on the _second_ instruction on the next page: */
1128 int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
1129 / sizeof(struct sparc_instr_call);
1130 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE-1)
1131 << SPARC_INSTR_ALIGNMENT_SHIFT);
1132 cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
1133
1134 /* This doesn't count as an executed instruction. */
1135 cpu->n_translated_instrs --;
1136
1137 quick_pc_to_pointers(cpu);
1138
1139 if (cpu->delay_slot == NOT_DELAYED)
1140 return;
1141
1142 fatal("end_of_page2: fatal error, we're in a delay slot\n");
1143 exit(1);
1144 }
1145
1146
1147 /*****************************************************************************/
1148
1149
1150 /*
1151 * sparc_instr_to_be_translated():
1152 *
1153 * Translate an instruction word into a sparc_instr_call. ic is filled in with
1154 * valid data for the translated instruction, or a "nothing" instruction if
1155 * there was a translation failure. The newly translated instruction is then
1156 * executed.
1157 */
1158 X(to_be_translated)
1159 {
1160 MODE_uint_t addr;
1161 int low_pc, in_crosspage_delayslot = 0;
1162 uint32_t iword;
1163 unsigned char *page;
1164 unsigned char ib[4];
1165 int main_opcode, op2, rd, rs1, rs2, btype, asi, cc, p, use_imm, x64 = 0;
1166 int store, signedness, size;
1167 int32_t tmpi32, siconst;
1168 /* void (*samepage_function)(struct cpu *, struct sparc_instr_call *);*/
1169
1170 /* Figure out the (virtual) address of the instruction: */
1171 low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
1172 / sizeof(struct sparc_instr_call);
1173
1174 /* Special case for branch with delayslot on the next page: */
1175 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
1176 /* fatal("[ delay-slot translation across page "
1177 "boundary ]\n"); */
1178 in_crosspage_delayslot = 1;
1179 }
1180
1181 addr = cpu->pc & ~((SPARC_IC_ENTRIES_PER_PAGE-1)
1182 << SPARC_INSTR_ALIGNMENT_SHIFT);
1183 addr += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
1184 cpu->pc = addr;
1185 addr &= ~((1 << SPARC_INSTR_ALIGNMENT_SHIFT) - 1);
1186
1187 /* Read the instruction word from memory: */
1188 #ifdef MODE32
1189 page = cpu->cd.sparc.host_load[addr >> 12];
1190 #else
1191 {
1192 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1193 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1194 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1195 uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
1196 uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1197 uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
1198 DYNTRANS_L3N)) & mask3;
1199 struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.sparc.l1_64[x1];
1200 struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
1201 page = l3->host_load[x3];
1202 }
1203 #endif
1204
1205 if (page != NULL) {
1206 /* fatal("TRANSLATION HIT!\n"); */
1207 memcpy(ib, page + (addr & 0xffc), sizeof(ib));
1208 } else {
1209 /* fatal("TRANSLATION MISS!\n"); */
1210 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
1211 sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
1212 fatal("to_be_translated(): "
1213 "read failed: TODO\n");
1214 goto bad;
1215 }
1216 }
1217
1218 /* SPARC instruction words are always big-endian. Convert
1219 to host order: */
1220 iword = BE32_TO_HOST( *((uint32_t *)&ib[0]) );
1221
1222
1223 #define DYNTRANS_TO_BE_TRANSLATED_HEAD
1224 #include "cpu_dyntrans.c"
1225 #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
1226
1227
1228 /*
1229 * Translate the instruction:
1230 */
1231
1232 main_opcode = iword >> 30;
1233 rd = (iword >> 25) & 31;
1234 btype = rd & (N_SPARC_BRANCH_TYPES - 1);
1235 rs1 = (iword >> 14) & 31;
1236 use_imm = (iword >> 13) & 1;
1237 asi = (iword >> 5) & 0xff;
1238 rs2 = iword & 31;
1239 siconst = (int16_t)((iword & 0x1fff) << 3) >> 3;
1240 op2 = (main_opcode == 0)? ((iword >> 22) & 7) : ((iword >> 19) & 0x3f);
1241 cc = (iword >> 20) & 3;
1242 p = (iword >> 19) & 1;
1243
1244 switch (main_opcode) {
1245
1246 case 0: switch (op2) {
1247
1248 case 1: /* branch (icc or xcc) */
1249 tmpi32 = (iword << 13);
1250 tmpi32 >>= 11;
1251 ic->arg[0] = (int32_t)tmpi32 + (addr & 0xffc);
1252 /* rd contains the annul bit concatenated with 4 bits
1253 of condition code. cc=0 for icc, 2 for xcc: */
1254 /* TODO: samepage */
1255 switch (rd + (cc << 5)) {
1256 case 0x01: ic->f = instr(be); break;
1257 case 0x02: ic->f = instr(ble); break;
1258 case 0x03: ic->f = instr(bl); break;
1259 case 0x08: ic->f = instr(ba); break;
1260 case 0x09: ic->f = instr(bne); break;
1261 case 0x0a: ic->f = instr(bg); break;
1262 case 0x0b: ic->f = instr(bge); break;
1263 case 0x19: ic->f = instr(bne_a); break;
1264 case 0x41: ic->f = instr(be_xcc); break;
1265 case 0x42: ic->f = instr(ble_xcc);break;
1266 case 0x43: ic->f = instr(bl_xcc); break;
1267 case 0x48: ic->f = instr(ba); break;
1268 case 0x4a: ic->f = instr(bg_xcc); break;
1269 case 0x4b: ic->f = instr(bge_xcc);break;
1270 default:fatal("Unimplemented branch, 0x%x\n",
1271 rd + (cc<<5));
1272 goto bad;
1273 }
1274 break;
1275
1276 case 2: /* branch (32-bit integer comparison) */
1277 tmpi32 = (iword << 10);
1278 tmpi32 >>= 8;
1279 ic->arg[0] = (int32_t)tmpi32 + (addr & 0xffc);
1280 /* rd contains the annul bit concatenated with 4 bits
1281 of condition code: */
1282 /* TODO: samepage */
1283 switch (rd) {
1284 case 0x01: ic->f = instr(be); break;
1285 case 0x03: ic->f = instr(bl); break;
1286 case 0x08: ic->f = instr(ba); break;
1287 case 0x09: ic->f = instr(bne); break;
1288 case 0x0b: ic->f = instr(bge); break;
1289 default:fatal("Unimplemented branch rd=%i\n", rd);
1290 goto bad;
1291 }
1292 break;
1293
1294 case 3: /* branch on register, 64-bit integer comparison */
1295 tmpi32 = ((iword & 0x300000) >> 6) | (iword & 0x3fff);
1296 tmpi32 <<= 16;
1297 tmpi32 >>= 14;
1298 ic->arg[0] = (int32_t)tmpi32 + (addr & 0xffc);
1299 ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs1];
1300 /* TODO: samepage */
1301 switch (btype) {
1302 case 0x05: ic->f = instr(brnz); break;
1303 default:fatal("Unimplemented branch 0x%x\n", rd);
1304 goto bad;
1305 }
1306 break;
1307
1308 case 4: /* sethi */
1309 ic->arg[0] = (size_t)&cpu->cd.sparc.r[rd];
1310 ic->arg[1] = (iword & 0x3fffff) << 10;
1311 ic->f = instr(set);
1312 if (rd == SPARC_ZEROREG)
1313 ic->f = instr(nop);
1314 break;
1315
1316 default:fatal("TODO: unimplemented op2=%i for main "
1317 "opcode %i\n", op2, main_opcode);
1318 goto bad;
1319 }
1320 break;
1321
1322 case 1: /* call and link */
1323 tmpi32 = (iword << 2);
1324 ic->arg[0] = (int32_t)tmpi32;
1325 ic->arg[1] = addr & 0xffc;
1326 if (cpu->machine->show_trace_tree)
1327 ic->f = instr(call_trace);
1328 else
1329 ic->f = instr(call);
1330 /* TODO: samepage */
1331 break;
1332
1333 case 2: switch (op2) {
1334
1335 case 0: /* add */
1336 case 1: /* and */
1337 case 2: /* or */
1338 case 3: /* xor */
1339 case 4: /* sub */
1340 case 5: /* andn */
1341 case 14:/* udiv */
1342 case 16:/* addcc */
1343 case 17:/* andcc */
1344 case 20:/* subcc (cmp) */
1345 case 37:/* sll */
1346 case 38:/* srl */
1347 case 39:/* sra */
1348 case 60:/* save */
1349 ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1];
1350 ic->f = NULL;
1351 if (use_imm) {
1352 ic->arg[1] = siconst;
1353 switch (op2) {
1354 case 0: ic->f = instr(add_imm); break;
1355 case 1: ic->f = instr(and_imm); break;
1356 case 2: ic->f = instr(or_imm); break;
1357 case 3: ic->f = instr(xor_imm); break;
1358 case 4: ic->f = instr(sub_imm); break;
1359 case 5: ic->f = instr(andn_imm); break;
1360 case 14:ic->f = instr(udiv_imm); break;
1361 case 16:ic->f = instr(addcc_imm); break;
1362 case 17:ic->f = instr(andcc_imm); break;
1363 case 20:ic->f = instr(subcc_imm); break;
1364 case 37:if (siconst & 0x1000) {
1365 ic->f = instr(sllx_imm);
1366 ic->arg[1] &= 63;
1367 x64 = 1;
1368 } else {
1369 ic->f = instr(sll_imm);
1370 ic->arg[1] &= 31;
1371 }
1372 break;
1373 case 38:if (siconst & 0x1000) {
1374 ic->f = instr(srlx_imm);
1375 ic->arg[1] &= 63;
1376 x64 = 1;
1377 } else {
1378 ic->f = instr(srl_imm);
1379 ic->arg[1] &= 31;
1380 }
1381 break;
1382 case 39:if (siconst & 0x1000) {
1383 ic->f = instr(srax_imm);
1384 ic->arg[1] &= 63;
1385 x64 = 1;
1386 } else {
1387 ic->f = instr(sra_imm);
1388 ic->arg[1] &= 31;
1389 }
1390 break;
1391 case 60:switch (cpu->cd.sparc.cpu_type.v) {
1392 case 9: ic->f = instr(save_v9_imm);
1393 break;
1394 default:fatal("only for v9 so far\n");
1395 goto bad;
1396 }
1397 }
1398 } else {
1399 ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2];
1400 switch (op2) {
1401 case 0: ic->f = instr(add); break;
1402 case 1: ic->f = instr(and); break;
1403 case 2: ic->f = instr(or); break;
1404 case 3: ic->f = instr(xor); break;
1405 case 4: ic->f = instr(sub); break;
1406 case 5: ic->f = instr(andn); break;
1407 case 14:ic->f = instr(udiv); break;
1408 case 16:ic->f = instr(addcc); break;
1409 case 17:ic->f = instr(andcc); break;
1410 case 20:ic->f = instr(subcc); break;
1411 case 37:if (siconst & 0x1000) {
1412 ic->f = instr(sllx);
1413 x64 = 1;
1414 } else
1415 ic->f = instr(sll);
1416 break;
1417 case 38:if (siconst & 0x1000) {
1418 ic->f = instr(srlx);
1419 x64 = 1;
1420 } else
1421 ic->f = instr(srl);
1422 break;
1423 case 39:if (siconst & 0x1000) {
1424 ic->f = instr(srax);
1425 x64 = 1;
1426 } else
1427 ic->f = instr(sra);
1428 break;
1429 }
1430 }
1431 if (ic->f == NULL) {
1432 fatal("TODO: Unimplemented instruction "
1433 "(possibly missed use_imm impl.)\n");
1434 goto bad;
1435 }
1436 ic->arg[2] = (size_t)&cpu->cd.sparc.r[rd];
1437 if (rd == SPARC_ZEROREG) {
1438 /*
1439 * Some opcodes should write to the scratch
1440 * register instead of becoming NOPs, when
1441 * rd is the zero register.
1442 *
1443 * Any opcode which updates the condition
1444 * codes, or anything which changes register
1445 * windows.
1446 */
1447 switch (op2) {
1448 case 16:/* addcc */
1449 case 17:/* andcc */
1450 case 20:/* subcc */
1451 case 60:/* save */
1452 ic->arg[2] = (size_t)
1453 &cpu->cd.sparc.scratch;
1454 break;
1455 default:ic->f = instr(nop);
1456 }
1457 }
1458 break;
1459
1460 case 41:/* rd %psr,%gpr on pre-sparcv9 */
1461 if (cpu->is_32bit) {
1462 ic->f = instr(rd_psr);
1463 ic->arg[2] = (size_t)&cpu->cd.sparc.r[rd];
1464 if (rd == SPARC_ZEROREG)
1465 ic->f = instr(nop);
1466 } else {
1467 fatal("opcode 2,41 not yet implemented"
1468 " for 64-bit cpus\n");
1469 goto bad;
1470 }
1471 break;
1472
1473 case 42:/* rdpr on sparcv9 */
1474 if (cpu->is_32bit) {
1475 fatal("opcode 2,42 not yet implemented"
1476 " for 32-bit cpus\n");
1477 goto bad;
1478 }
1479 ic->arg[2] = (size_t)&cpu->cd.sparc.r[rd];
1480 if (rd == SPARC_ZEROREG)
1481 ic->f = instr(nop);
1482 switch (rs1) {
1483 case 5: ic->f = instr(rdpr_tba); break;
1484 case 31: ic->f = instr(rdpr_ver); break;
1485 default:fatal("Unimplemented rs1=%i\n", rs1);
1486 goto bad;
1487 }
1488 break;
1489
1490 case 43:if (iword == 0x81580000) {
1491 ic->f = instr(flushw);
1492 } else {
1493 fatal("Unimplemented iword=0x%08"PRIx32"\n",
1494 iword);
1495 goto bad;
1496 }
1497 break;
1498
1499 case 48:/* wr (Note: works as xor) */
1500 ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1];
1501 if (use_imm) {
1502 ic->arg[1] = siconst;
1503 ic->f = instr(xor_imm);
1504 } else {
1505 ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2];
1506 ic->f = instr(xor);
1507 }
1508 ic->arg[2] = (size_t) NULL;
1509 switch (rd) {
1510 case 0: ic->arg[2] = (size_t)&cpu->cd.sparc.y;
1511 break;
1512 case 6: ic->arg[2] = (size_t)&cpu->cd.sparc.fprs;
1513 break;
1514 case 0x17:
1515 ic->arg[2] = (size_t)&cpu->cd.sparc.tick_cmpr;
1516 break;
1517 }
1518 if (ic->arg[2] == (size_t)NULL) {
1519 fatal("TODO: Unimplemented wr instruction, "
1520 "rd = 0x%02x\n", rd);
1521 goto bad;
1522 }
1523 break;
1524
1525 case 50:/* wrpr (Note: works as xor) */
1526 ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1];
1527 ic->f = NULL;
1528 if (use_imm) {
1529 ic->arg[1] = siconst;
1530 switch (rd) {
1531 case 4: ic->f = instr(wrpr_tick_imm); break;
1532 case 6: ic->f = instr(wrpr_pstate_imm); break;
1533 case 8: ic->f = instr(wrpr_pil_imm); break;
1534 case 12:ic->f = instr(wrpr_cleanwin_imm);break;
1535 }
1536 } else {
1537 ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2];
1538 switch (rd) {
1539 case 4: ic->f = instr(wrpr_tick); break;
1540 case 6: ic->f = instr(wrpr_pstate); break;
1541 case 8: ic->f = instr(wrpr_pil); break;
1542 case 12:ic->f = instr(wrpr_cleanwin); break;
1543 }
1544 }
1545 if (ic->f == NULL) {
1546 fatal("TODO: Unimplemented wrpr instruction,"
1547 " rd = 0x%02x\n", rd);
1548 goto bad;
1549 }
1550 break;
1551
1552 case 56:/* jump and link */
1553 ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1];
1554 ic->arg[2] = (size_t)&cpu->cd.sparc.r[rd];
1555 if (rd == SPARC_ZEROREG)
1556 ic->arg[2] = (size_t)&cpu->cd.sparc.scratch;
1557
1558 if (use_imm) {
1559 ic->arg[1] = siconst;
1560 if (rd == SPARC_ZEROREG)
1561 ic->f = instr(jmpl_imm_no_rd);
1562 else
1563 ic->f = instr(jmpl_imm);
1564 } else {
1565 ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2];
1566 if (rd == SPARC_ZEROREG)
1567 ic->f = instr(jmpl_reg_no_rd);
1568 else
1569 ic->f = instr(jmpl_reg);
1570 }
1571
1572 /* special trace case: */
1573 if (cpu->machine->show_trace_tree) {
1574 if (iword == 0x81c3e008)
1575 ic->f = instr(retl_trace);
1576 else {
1577 if (use_imm)
1578 ic->f = instr(jmpl_imm_trace);
1579 else
1580 ic->f = instr(jmpl_reg_trace);
1581 }
1582 }
1583 break;
1584
1585 case 57:/* return */
1586 ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1];
1587
1588 if (use_imm) {
1589 ic->arg[1] = siconst;
1590 ic->f = instr(return_imm);
1591 } else {
1592 ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2];
1593 ic->f = instr(return_reg);
1594 }
1595
1596 /* special trace case: */
1597 if (cpu->machine->show_trace_tree) {
1598 if (use_imm)
1599 ic->f = instr(return_imm_trace);
1600 else
1601 ic->f = instr(return_reg_trace);
1602 }
1603 break;
1604
1605 default:fatal("TODO: unimplemented op2=%i for main "
1606 "opcode %i\n", op2, main_opcode);
1607 goto bad;
1608 }
1609 break;
1610
1611 case 3: switch (op2) {
1612
1613 case 0:/* lduw */
1614 case 1:/* ldub */
1615 case 2:/* lduh */
1616 case 4:/* st(w) */
1617 case 5:/* stb */
1618 case 6:/* sth */
1619 case 8:/* ldsw */
1620 case 9:/* ldsb */
1621 case 10:/* ldsh */
1622 case 11:/* ldx */
1623 case 14:/* stx */
1624 store = 1; signedness = 0; size = 3;
1625 switch (op2) {
1626 case 0: /* lduw */ store=0; size=2; break;
1627 case 1: /* ldub */ store=0; size=0; break;
1628 case 2: /* lduh */ store=0; size=1; break;
1629 case 4: /* st */ size = 2; break;
1630 case 5: /* stb */ size = 0; break;
1631 case 6: /* sth */ size = 1; break;
1632 case 8: /* ldsw */ store=0; size=2; signedness=1;
1633 break;
1634 case 9: /* ldsb */ store=0; size=0; signedness=1;
1635 break;
1636 case 10: /* ldsh */ store=0; size=1; signedness=1;
1637 break;
1638 case 11: /* ldx */ store=0; break;
1639 case 14: /* stx */ break;
1640 }
1641 ic->f =
1642 #ifdef MODE32
1643 sparc32_loadstore
1644 #else
1645 sparc_loadstore
1646 #endif
1647 [ use_imm*16 + store*8 + size*2 + signedness ];
1648
1649 ic->arg[0] = (size_t)&cpu->cd.sparc.r[rd];
1650 ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs1];
1651 if (use_imm)
1652 ic->arg[2] = siconst;
1653 else
1654 ic->arg[2] = (size_t)&cpu->cd.sparc.r[rs2];
1655
1656 if (!store && rd == SPARC_ZEROREG)
1657 ic->arg[0] = (size_t)&cpu->cd.sparc.scratch;
1658
1659 break;
1660
1661 default:fatal("TODO: unimplemented op2=%i for main "
1662 "opcode %i\n", op2, main_opcode);
1663 goto bad;
1664 }
1665 break;
1666
1667 }
1668
1669
1670 if (x64 && cpu->is_32bit) {
1671 fatal("TODO: 64-bit instr on 32-bit cpu\n");
1672 goto bad;
1673 }
1674
1675
1676 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
1677 #include "cpu_dyntrans.c"
1678 #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
1679 }
1680

  ViewVC Help
Powered by ViewVC 1.1.26