25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_sparc_instr.c,v 1.18 2006/05/17 20:27:31 debug Exp $ |
* $Id: cpu_sparc_instr.c,v 1.21 2006/07/02 11:01:19 debug Exp $ |
29 |
* |
* |
30 |
* SPARC instructions. |
* SPARC instructions. |
31 |
* |
* |
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. |
* nop: Do nothing. |
53 |
*/ |
*/ |
54 |
X(nop) |
X(nop) |
339 |
|
|
340 |
|
|
341 |
/* |
/* |
342 |
|
* Save: |
343 |
|
* |
344 |
|
* arg[0] = ptr to rs1 |
345 |
|
* arg[1] = ptr to rs2 or an immediate value (int32_t) |
346 |
|
* arg[2] = ptr to rd (_after_ the register window change) |
347 |
|
*/ |
348 |
|
X(save_v9_imm) |
349 |
|
{ |
350 |
|
MODE_uint_t rs = reg(ic->arg[0]) + (int32_t)ic->arg[1]; |
351 |
|
int cwp = cpu->cd.sparc.cwp; |
352 |
|
|
353 |
|
if (cpu->cd.sparc.cansave == 0) { |
354 |
|
fatal("save_v9_imm: spill trap. TODO\n"); |
355 |
|
exit(1); |
356 |
|
} |
357 |
|
|
358 |
|
if (cpu->cd.sparc.cleanwin - cpu->cd.sparc.canrestore == 0) { |
359 |
|
fatal("save_v9_imm: clean_window trap. TODO\n"); |
360 |
|
exit(1); |
361 |
|
} |
362 |
|
|
363 |
|
/* Save away old in registers: */ |
364 |
|
memcpy(&cpu->cd.sparc.r_inout[cwp][0], &cpu->cd.sparc.r[SPARC_REG_I0], |
365 |
|
sizeof(cpu->cd.sparc.r[SPARC_REG_I0]) * N_SPARC_INOUT_REG); |
366 |
|
|
367 |
|
/* Save away old local registers: */ |
368 |
|
memcpy(&cpu->cd.sparc.r_local[cwp][0], &cpu->cd.sparc.r[SPARC_REG_L0], |
369 |
|
sizeof(cpu->cd.sparc.r[SPARC_REG_L0]) * N_SPARC_INOUT_REG); |
370 |
|
|
371 |
|
cwp = cpu->cd.sparc.cwp = (cwp + 1) % cpu->cd.sparc.cpu_type.nwindows; |
372 |
|
cpu->cd.sparc.cansave --; |
373 |
|
cpu->cd.sparc.canrestore ++; /* TODO: modulo here too? */ |
374 |
|
|
375 |
|
/* The out registers become the new in registers: */ |
376 |
|
memcpy(&cpu->cd.sparc.r[SPARC_REG_I0], &cpu->cd.sparc.r[SPARC_REG_O0], |
377 |
|
sizeof(cpu->cd.sparc.r[SPARC_REG_O0]) * N_SPARC_INOUT_REG); |
378 |
|
|
379 |
|
/* Read new local registers: */ |
380 |
|
memcpy(&cpu->cd.sparc.r[SPARC_REG_L0], &cpu->cd.sparc.r_local[cwp][0], |
381 |
|
sizeof(cpu->cd.sparc.r[SPARC_REG_L0]) * N_SPARC_INOUT_REG); |
382 |
|
|
383 |
|
reg(ic->arg[2]) = rs; |
384 |
|
} |
385 |
|
|
386 |
|
|
387 |
|
/* |
388 |
* Subtract with ccr update: |
* Subtract with ccr update: |
389 |
* |
* |
390 |
* arg[0] = ptr to rs1 |
* arg[0] = ptr to rs1 |
441 |
} |
} |
442 |
|
|
443 |
|
|
444 |
|
#include "tmp_sparc_loadstore.c" |
445 |
|
|
446 |
|
|
447 |
/* |
/* |
448 |
* rd: Read special register: |
* rd: Read special register: |
449 |
* |
* |
544 |
X(to_be_translated) |
X(to_be_translated) |
545 |
{ |
{ |
546 |
MODE_uint_t addr; |
MODE_uint_t addr; |
547 |
int low_pc; |
int low_pc, in_crosspage_delayslot = 0; |
|
int in_crosspage_delayslot = 0; |
|
548 |
uint32_t iword; |
uint32_t iword; |
549 |
unsigned char *page; |
unsigned char *page; |
550 |
unsigned char ib[4]; |
unsigned char ib[4]; |
551 |
int main_opcode, op2, rd, rs1, rs2, btype, asi, cc, p, use_imm, x64 = 0; |
int main_opcode, op2, rd, rs1, rs2, btype, asi, cc, p, use_imm, x64 = 0; |
552 |
|
int store, signedness, size; |
553 |
int32_t tmpi32, siconst; |
int32_t tmpi32, siconst; |
554 |
/* void (*samepage_function)(struct cpu *, struct sparc_instr_call *);*/ |
/* void (*samepage_function)(struct cpu *, struct sparc_instr_call *);*/ |
555 |
|
|
682 |
case 37:/* sll */ |
case 37:/* sll */ |
683 |
case 38:/* srl */ |
case 38:/* srl */ |
684 |
case 39:/* sra */ |
case 39:/* sra */ |
685 |
|
case 60:/* save */ |
686 |
ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1]; |
ic->arg[0] = (size_t)&cpu->cd.sparc.r[rs1]; |
687 |
ic->f = NULL; |
ic->f = NULL; |
688 |
if (use_imm) { |
if (use_imm) { |
721 |
ic->arg[1] &= 31; |
ic->arg[1] &= 31; |
722 |
} |
} |
723 |
break; |
break; |
724 |
|
case 60:switch (cpu->cd.sparc.cpu_type.v) { |
725 |
|
case 9: ic->f = instr(save_v9_imm); |
726 |
|
break; |
727 |
|
default:fatal("only for v9 so far\n"); |
728 |
|
goto bad; |
729 |
|
} |
730 |
} |
} |
731 |
} else { |
} else { |
732 |
ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2]; |
ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs2]; |
764 |
} |
} |
765 |
ic->arg[2] = (size_t)&cpu->cd.sparc.r[rd]; |
ic->arg[2] = (size_t)&cpu->cd.sparc.r[rd]; |
766 |
if (rd == SPARC_ZEROREG) { |
if (rd == SPARC_ZEROREG) { |
767 |
/* Opcodes which update the ccr should use |
/* |
768 |
the scratch register instead of being |
* Some opcodes should write to the scratch |
769 |
turned into a nop, when the zero register |
* register instead of becoming NOPs, when |
770 |
is used as the destination: */ |
* rd is the zero register. |
771 |
|
*/ |
772 |
switch (op2) { |
switch (op2) { |
773 |
case 20:/* subcc */ |
case 20:/* subcc */ |
774 |
|
case 60:/* save */ |
775 |
ic->arg[2] = (size_t) |
ic->arg[2] = (size_t) |
776 |
&cpu->cd.sparc.scratch; |
&cpu->cd.sparc.scratch; |
777 |
break; |
break; |
883 |
} |
} |
884 |
break; |
break; |
885 |
|
|
886 |
default:fatal("TODO: unimplemented main opcode %i\n", main_opcode); |
case 3: switch (op2) { |
887 |
goto bad; |
|
888 |
|
case 0:/* lduw */ |
889 |
|
case 1:/* ldub */ |
890 |
|
case 2:/* lduh */ |
891 |
|
case 4:/* st(w) */ |
892 |
|
case 5:/* stb */ |
893 |
|
case 6:/* sth */ |
894 |
|
case 8:/* ldsw */ |
895 |
|
case 9:/* ldsb */ |
896 |
|
case 10:/* ldsh */ |
897 |
|
case 11:/* ldx */ |
898 |
|
case 14:/* stx */ |
899 |
|
store = 1; signedness = 0; size = 3; |
900 |
|
switch (op2) { |
901 |
|
case 0: /* lduw */ store=0; size=2; break; |
902 |
|
case 1: /* ldub */ store=0; size=0; break; |
903 |
|
case 2: /* lduh */ store=0; size=1; break; |
904 |
|
case 4: /* st */ size = 2; break; |
905 |
|
case 5: /* stb */ size = 0; break; |
906 |
|
case 6: /* sth */ size = 1; break; |
907 |
|
case 8: /* ldsw */ store=0; size=2; signedness=1; |
908 |
|
break; |
909 |
|
case 9: /* ldsb */ store=0; size=0; signedness=1; |
910 |
|
break; |
911 |
|
case 10: /* ldsh */ store=0; size=1; signedness=1; |
912 |
|
break; |
913 |
|
case 11: /* ldx */ store=0; break; |
914 |
|
case 14: /* stx */ break; |
915 |
|
} |
916 |
|
ic->f = |
917 |
|
#ifdef MODE32 |
918 |
|
sparc32_loadstore |
919 |
|
#else |
920 |
|
sparc_loadstore |
921 |
|
#endif |
922 |
|
[ use_imm*16 + store*8 + size*2 + signedness ]; |
923 |
|
|
924 |
|
ic->arg[0] = (size_t)&cpu->cd.sparc.r[rd]; |
925 |
|
ic->arg[1] = (size_t)&cpu->cd.sparc.r[rs1]; |
926 |
|
if (use_imm) |
927 |
|
ic->arg[2] = siconst; |
928 |
|
else |
929 |
|
ic->arg[2] = (size_t)&cpu->cd.sparc.r[rs2]; |
930 |
|
|
931 |
|
if (!store && rd == SPARC_ZEROREG) |
932 |
|
ic->arg[0] = (size_t)&cpu->cd.sparc.scratch; |
933 |
|
|
934 |
|
break; |
935 |
|
|
936 |
|
default:fatal("TODO: unimplemented op2=%i for main " |
937 |
|
"opcode %i\n", op2, main_opcode); |
938 |
|
goto bad; |
939 |
|
} |
940 |
|
break; |
941 |
|
|
942 |
} |
} |
943 |
|
|
944 |
|
|