/[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 30 - (hide annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 39133 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26