/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 5 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 dpavlin 14 /*
2 dpavlin 34 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 dpavlin 14 *
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 dpavlin 44 * $Id: cpu_sparc_instr.c,v 1.29 2007/06/28 13:36:47 debug Exp $
29 dpavlin 14 *
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 dpavlin 28 * 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 dpavlin 14 * nop: Do nothing.
53     */
54     X(nop)
55     {
56     }
57    
58    
59     /*****************************************************************************/
60    
61    
62 dpavlin 24 /*
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 dpavlin 30 * 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 dpavlin 32 * 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 dpavlin 30 * 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 dpavlin 24 * 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 dpavlin 30 * 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 dpavlin 32 * 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 dpavlin 24 * 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 dpavlin 32 * 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 dpavlin 24 * 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 dpavlin 32 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 dpavlin 24 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 dpavlin 30 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 dpavlin 24
853 dpavlin 30
854 dpavlin 24 /*
855 dpavlin 30 * 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 dpavlin 24 * 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 dpavlin 28 #include "tmp_sparc_loadstore.c"
1020    
1021    
1022 dpavlin 24 /*
1023 dpavlin 36 * 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 dpavlin 30 * rd: Read special register
1039 dpavlin 24 *
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 dpavlin 30 * 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 dpavlin 24 * 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 dpavlin 36 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 dpavlin 24
1105    
1106     /*****************************************************************************/
1107    
1108    
1109 dpavlin 14 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 dpavlin 24 quick_pc_to_pointers(cpu);
1119 dpavlin 14
1120     /* end_of_page doesn't count as an executed instruction: */
1121     cpu->n_translated_instrs --;
1122     }
1123    
1124    
1125 dpavlin 24 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 dpavlin 14 /*****************************************************************************/
1148    
1149    
1150     /*
1151     * sparc_instr_to_be_translated():
1152     *
1153 dpavlin 24 * Translate an instruction word into a sparc_instr_call. ic is filled in with
1154 dpavlin 14 * 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 dpavlin 24 MODE_uint_t addr;
1161 dpavlin 28 int low_pc, in_crosspage_delayslot = 0;
1162 dpavlin 14 uint32_t iword;
1163     unsigned char *page;
1164     unsigned char ib[4];
1165 dpavlin 24 int main_opcode, op2, rd, rs1, rs2, btype, asi, cc, p, use_imm, x64 = 0;
1166 dpavlin 28 int store, signedness, size;
1167 dpavlin 24 int32_t tmpi32, siconst;
1168 dpavlin 20 /* void (*samepage_function)(struct cpu *, struct sparc_instr_call *);*/
1169 dpavlin 14
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 dpavlin 24
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 dpavlin 14 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 dpavlin 24 #ifdef MODE32
1189 dpavlin 14 page = cpu->cd.sparc.host_load[addr >> 12];
1190 dpavlin 24 #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 dpavlin 14
1205     if (page != NULL) {
1206     /* fatal("TRANSLATION HIT!\n"); */
1207 dpavlin 24 memcpy(ib, page + (addr & 0xffc), sizeof(ib));
1208 dpavlin 14 } 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 dpavlin 24 /* SPARC instruction words are always big-endian. Convert
1219     to host order: */
1220     iword = BE32_TO_HOST( *((uint32_t *)&ib[0]) );
1221 dpavlin 14
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 dpavlin 24 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 dpavlin 14
1244     switch (main_opcode) {
1245    
1246 dpavlin 24 case 0: switch (op2) {
1247    
1248 dpavlin 30 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 dpavlin 32 case 0x02: ic->f = instr(ble); break;
1258 dpavlin 30 case 0x03: ic->f = instr(bl); break;
1259 dpavlin 32 case 0x08: ic->f = instr(ba); break;
1260 dpavlin 30 case 0x09: ic->f = instr(bne); break;
1261 dpavlin 32 case 0x0a: ic->f = instr(bg); break;
1262 dpavlin 30 case 0x0b: ic->f = instr(bge); break;
1263 dpavlin 32 case 0x19: ic->f = instr(bne_a); break;
1264 dpavlin 30 case 0x41: ic->f = instr(be_xcc); break;
1265 dpavlin 32 case 0x42: ic->f = instr(ble_xcc);break;
1266 dpavlin 30 case 0x43: ic->f = instr(bl_xcc); break;
1267 dpavlin 32 case 0x48: ic->f = instr(ba); break;
1268 dpavlin 30 case 0x4a: ic->f = instr(bg_xcc); break;
1269 dpavlin 32 case 0x4b: ic->f = instr(bge_xcc);break;
1270 dpavlin 30 default:fatal("Unimplemented branch, 0x%x\n",
1271     rd + (cc<<5));
1272     goto bad;
1273     }
1274     break;
1275    
1276 dpavlin 24 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 dpavlin 30 case 0x01: ic->f = instr(be); break;
1285     case 0x03: ic->f = instr(bl); break;
1286     case 0x08: ic->f = instr(ba); break;
1287 dpavlin 32 case 0x09: ic->f = instr(bne); break;
1288 dpavlin 30 case 0x0b: ic->f = instr(bge); break;
1289     default:fatal("Unimplemented branch rd=%i\n", rd);
1290     goto bad;
1291 dpavlin 24 }
1292     break;
1293    
1294 dpavlin 30 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 dpavlin 24 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 dpavlin 32 case 5: /* andn */
1341 dpavlin 30 case 14:/* udiv */
1342     case 16:/* addcc */
1343     case 17:/* andcc */
1344 dpavlin 24 case 20:/* subcc (cmp) */
1345     case 37:/* sll */
1346     case 38:/* srl */
1347     case 39:/* sra */
1348 dpavlin 28 case 60:/* save */
1349 dpavlin 24 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 dpavlin 32 case 5: ic->f = instr(andn_imm); break;
1360 dpavlin 30 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 dpavlin 24 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 dpavlin 28 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 dpavlin 24 }
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 dpavlin 32 case 5: ic->f = instr(andn); break;
1407 dpavlin 30 case 14:ic->f = instr(udiv); break;
1408     case 16:ic->f = instr(addcc); break;
1409     case 17:ic->f = instr(andcc); break;
1410 dpavlin 24 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 dpavlin 28 /*
1439     * Some opcodes should write to the scratch
1440     * register instead of becoming NOPs, when
1441     * rd is the zero register.
1442 dpavlin 30 *
1443     * Any opcode which updates the condition
1444     * codes, or anything which changes register
1445     * windows.
1446 dpavlin 28 */
1447 dpavlin 24 switch (op2) {
1448 dpavlin 30 case 16:/* addcc */
1449     case 17:/* andcc */
1450 dpavlin 24 case 20:/* subcc */
1451 dpavlin 28 case 60:/* save */
1452 dpavlin 24 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 dpavlin 30 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 dpavlin 36 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 dpavlin 24 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 dpavlin 36 case 12:ic->f = instr(wrpr_cleanwin_imm);break;
1535 dpavlin 24 }
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 dpavlin 36 case 12:ic->f = instr(wrpr_cleanwin); break;
1543 dpavlin 24 }
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 dpavlin 32 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 dpavlin 24 default:fatal("TODO: unimplemented op2=%i for main "
1606     "opcode %i\n", op2, main_opcode);
1607     goto bad;
1608     }
1609     break;
1610    
1611 dpavlin 28 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 dpavlin 14 }
1668    
1669    
1670 dpavlin 24 if (x64 && cpu->is_32bit) {
1671     fatal("TODO: 64-bit instr on 32-bit cpu\n");
1672     goto bad;
1673     }
1674    
1675    
1676 dpavlin 14 #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