/[gxemul]/upstream/0.4.4/src/cpus/cpu_sparc_instr.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.4.4/src/cpus/cpu_sparc_instr.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26