423 |
|
|
424 |
static inline void save_state(DisasContext * dc) |
static inline void save_state(DisasContext * dc) |
425 |
{ |
{ |
426 |
gen_op_jmp_im((uint32_t)dc->pc); |
gen_op_jmp_im(dc->pc); |
427 |
save_npc(dc); |
save_npc(dc); |
428 |
} |
} |
429 |
|
|
430 |
static void gen_cond(int cond) |
static void gen_cond(int cond) |
431 |
{ |
{ |
432 |
switch (cond) { |
switch (cond) { |
|
case 0x0: |
|
|
gen_op_movl_T2_0(); |
|
|
break; |
|
433 |
case 0x1: |
case 0x1: |
434 |
gen_op_eval_be(); |
gen_op_eval_be(); |
435 |
break; |
break; |
451 |
case 0x7: |
case 0x7: |
452 |
gen_op_eval_bvs(); |
gen_op_eval_bvs(); |
453 |
break; |
break; |
|
case 0x8: |
|
|
gen_op_movl_T2_1(); |
|
|
break; |
|
454 |
case 0x9: |
case 0x9: |
455 |
gen_op_eval_bne(); |
gen_op_eval_bne(); |
456 |
break; |
break; |
479 |
static void gen_fcond(int cond) |
static void gen_fcond(int cond) |
480 |
{ |
{ |
481 |
switch (cond) { |
switch (cond) { |
|
case 0x0: |
|
|
gen_op_movl_T2_0(); |
|
|
break; |
|
482 |
case 0x1: |
case 0x1: |
483 |
gen_op_eval_fbne(); |
gen_op_eval_fbne(); |
484 |
break; |
break; |
500 |
case 0x7: |
case 0x7: |
501 |
gen_op_eval_fbu(); |
gen_op_eval_fbu(); |
502 |
break; |
break; |
|
case 0x8: |
|
|
gen_op_movl_T2_1(); |
|
|
break; |
|
503 |
case 0x9: |
case 0x9: |
504 |
gen_op_eval_fbe(); |
gen_op_eval_fbe(); |
505 |
break; |
break; |
525 |
} |
} |
526 |
} |
} |
527 |
|
|
528 |
static void do_branch(DisasContext * dc, uint32_t target, uint32_t insn) |
static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn) |
529 |
{ |
{ |
530 |
unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29)); |
unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29)); |
531 |
target += (uint32_t) dc->pc; |
target_ulong target = dc->pc + offset; |
532 |
|
|
533 |
if (cond == 0x0) { |
if (cond == 0x0) { |
534 |
/* unconditional not taken */ |
/* unconditional not taken */ |
535 |
if (a) { |
if (a) { |
563 |
} |
} |
564 |
} |
} |
565 |
|
|
566 |
static void do_fbranch(DisasContext * dc, uint32_t target, uint32_t insn) |
static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn) |
567 |
{ |
{ |
568 |
unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29)); |
unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29)); |
569 |
target += (uint32_t) dc->pc; |
target_ulong target = dc->pc + offset; |
570 |
|
|
571 |
if (cond == 0x0) { |
if (cond == 0x0) { |
572 |
/* unconditional not taken */ |
/* unconditional not taken */ |
573 |
if (a) { |
if (a) { |
601 |
} |
} |
602 |
} |
} |
603 |
|
|
|
#if 0 |
|
|
static void gen_debug(DisasContext *s, uint32_t pc) |
|
|
{ |
|
|
gen_op_jmp_im(pc); |
|
|
gen_op_debug(); |
|
|
s->is_br = 1; |
|
|
} |
|
|
#endif |
|
|
|
|
604 |
#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1) |
#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1) |
605 |
|
|
606 |
static int sign_extend(int x, int len) |
static int sign_extend(int x, int len) |
621 |
case 0: /* branches/sethi */ |
case 0: /* branches/sethi */ |
622 |
{ |
{ |
623 |
unsigned int xop = GET_FIELD(insn, 7, 9); |
unsigned int xop = GET_FIELD(insn, 7, 9); |
624 |
int target; |
int32_t target; |
625 |
target = GET_FIELD(insn, 10, 31); |
target = GET_FIELD(insn, 10, 31); |
626 |
switch (xop) { |
switch (xop) { |
627 |
case 0x0: |
case 0x0: /* UNIMPL */ |
628 |
case 0x1: /* UNIMPL */ |
case 0x1: /* V9 BPcc */ |
629 |
case 0x5: /*CBN+x */ |
case 0x3: /* V9 BPr */ |
630 |
|
case 0x5: /* V9 FBPcc */ |
631 |
default: |
default: |
632 |
goto illegal_insn; |
goto illegal_insn; |
633 |
case 0x2: /* BN+x */ |
case 0x2: /* BN+x */ |
661 |
} |
} |
662 |
break; |
break; |
663 |
} |
} |
664 |
|
break; |
665 |
case 1: |
case 1: |
666 |
/*CALL*/ { |
/*CALL*/ { |
667 |
unsigned int target = GET_FIELDs(insn, 2, 31) << 2; |
target_long target = GET_FIELDs(insn, 2, 31) << 2; |
668 |
|
|
669 |
gen_op_movl_T0_im((long) (dc->pc)); |
gen_op_movl_T0_im(dc->pc); |
670 |
gen_movl_T0_reg(15); |
gen_movl_T0_reg(15); |
671 |
target = dc->pc + target; |
target += dc->pc; |
672 |
dc->pc = dc->npc; |
dc->pc = dc->npc; |
673 |
dc->npc = target; |
dc->npc = target; |
674 |
} |
} |
702 |
#endif |
#endif |
703 |
} |
} |
704 |
save_state(dc); |
save_state(dc); |
705 |
|
/* V9 icc/xcc */ |
706 |
cond = GET_FIELD(insn, 3, 6); |
cond = GET_FIELD(insn, 3, 6); |
707 |
if (cond == 0x8) { |
if (cond == 0x8) { |
708 |
gen_op_trap_T0(); |
gen_op_trap_T0(); |
709 |
dc->is_br = 1; |
dc->is_br = 1; |
710 |
goto jmp_insn; |
goto jmp_insn; |
711 |
} else { |
} else if (cond != 0) { |
712 |
gen_cond(cond); |
gen_cond(cond); |
713 |
gen_op_trapcc_T0(); |
gen_op_trapcc_T0(); |
714 |
} |
} |
719 |
gen_op_rdy(); |
gen_op_rdy(); |
720 |
gen_movl_T0_reg(rd); |
gen_movl_T0_reg(rd); |
721 |
break; |
break; |
722 |
case 15: /* stbar */ |
case 15: /* stbar / V9 membar */ |
723 |
break; /* no effect? */ |
break; /* no effect? */ |
724 |
default: |
default: |
725 |
|
case 0x2: /* V9 rdccr */ |
726 |
|
case 0x3: /* V9 rdasi */ |
727 |
|
case 0x4: /* V9 rdtick */ |
728 |
|
case 0x5: /* V9 rdpc */ |
729 |
|
case 0x6: /* V9 rdfprs */ |
730 |
goto illegal_insn; |
goto illegal_insn; |
731 |
} |
} |
732 |
#if !defined(CONFIG_USER_ONLY) |
#if !defined(CONFIG_USER_ONLY) |
890 |
case 0xd3: /* fqtoi */ |
case 0xd3: /* fqtoi */ |
891 |
goto nfpu_insn; |
goto nfpu_insn; |
892 |
default: |
default: |
893 |
|
case 0x2: /* V9 fmovd */ |
894 |
|
case 0x6: /* V9 fnegd */ |
895 |
|
case 0xa: /* V9 fabsd */ |
896 |
|
case 0x81: /* V9 fstox */ |
897 |
|
case 0x82: /* V9 fdtox */ |
898 |
|
case 0x84: /* V9 fxtos */ |
899 |
|
case 0x88: /* V9 fxtod */ |
900 |
|
|
901 |
|
case 0x3: /* V9 fmovq */ |
902 |
|
case 0x7: /* V9 fnegq */ |
903 |
|
case 0xb: /* V9 fabsq */ |
904 |
|
case 0x83: /* V9 fqtox */ |
905 |
|
case 0x8c: /* V9 fxtoq */ |
906 |
goto illegal_insn; |
goto illegal_insn; |
907 |
} |
} |
908 |
} else if (xop == 0x35) { /* FPU Operations */ |
} else if (xop == 0x35) { /* FPU Operations */ |
912 |
rs1 = GET_FIELD(insn, 13, 17); |
rs1 = GET_FIELD(insn, 13, 17); |
913 |
rs2 = GET_FIELD(insn, 27, 31); |
rs2 = GET_FIELD(insn, 27, 31); |
914 |
xop = GET_FIELD(insn, 18, 26); |
xop = GET_FIELD(insn, 18, 26); |
915 |
|
/* V9 fmovscc: x5, cond = x >> 1 */ |
916 |
|
/* V9 fmovdcc: x6, cond = x >> 1 */ |
917 |
|
|
918 |
|
/* V9 fmovqcc: x7, cond = x >> 1 */ |
919 |
switch (xop) { |
switch (xop) { |
920 |
case 0x51: |
case 0x51: |
921 |
gen_op_load_fpr_FT0(rs1); |
gen_op_load_fpr_FT0(rs1); |
1034 |
gen_op_logic_T0_cc(); |
gen_op_logic_T0_cc(); |
1035 |
break; |
break; |
1036 |
case 0x8: |
case 0x8: |
|
gen_op_addx_T1_T0(); |
|
1037 |
if (xop & 0x10) |
if (xop & 0x10) |
1038 |
gen_op_set_flags(); |
gen_op_addx_T1_T0_cc(); |
1039 |
|
else |
1040 |
|
gen_op_addx_T1_T0(); |
1041 |
break; |
break; |
1042 |
case 0xa: |
case 0xa: |
1043 |
gen_op_umul_T1_T0(); |
gen_op_umul_T1_T0(); |
1050 |
gen_op_logic_T0_cc(); |
gen_op_logic_T0_cc(); |
1051 |
break; |
break; |
1052 |
case 0xc: |
case 0xc: |
|
gen_op_subx_T1_T0(); |
|
1053 |
if (xop & 0x10) |
if (xop & 0x10) |
1054 |
gen_op_set_flags(); |
gen_op_subx_T1_T0_cc(); |
1055 |
|
else |
1056 |
|
gen_op_subx_T1_T0(); |
1057 |
break; |
break; |
1058 |
case 0xe: |
case 0xe: |
1059 |
gen_op_udiv_T1_T0(); |
gen_op_udiv_T1_T0(); |
1066 |
gen_op_div_cc(); |
gen_op_div_cc(); |
1067 |
break; |
break; |
1068 |
default: |
default: |
1069 |
|
case 0x9: /* V9 mulx */ |
1070 |
|
case 0xd: /* V9 udivx */ |
1071 |
goto illegal_insn; |
goto illegal_insn; |
1072 |
} |
} |
1073 |
gen_movl_T0_reg(rd); |
gen_movl_T0_reg(rd); |
1082 |
gen_op_mulscc_T1_T0(); |
gen_op_mulscc_T1_T0(); |
1083 |
gen_movl_T0_reg(rd); |
gen_movl_T0_reg(rd); |
1084 |
break; |
break; |
1085 |
case 0x25: /* SLL */ |
case 0x25: /* sll, V9 sllx */ |
1086 |
gen_op_sll(); |
gen_op_sll(); |
1087 |
gen_movl_T0_reg(rd); |
gen_movl_T0_reg(rd); |
1088 |
break; |
break; |
1089 |
case 0x26: |
case 0x26: /* srl, V9 srlx */ |
1090 |
gen_op_srl(); |
gen_op_srl(); |
1091 |
gen_movl_T0_reg(rd); |
gen_movl_T0_reg(rd); |
1092 |
break; |
break; |
1093 |
case 0x27: |
case 0x27: /* sra, V9 srax */ |
1094 |
gen_op_sra(); |
gen_op_sra(); |
1095 |
gen_movl_T0_reg(rd); |
gen_movl_T0_reg(rd); |
1096 |
break; |
break; |
1102 |
gen_op_wry(); |
gen_op_wry(); |
1103 |
break; |
break; |
1104 |
default: |
default: |
1105 |
|
case 0x2: /* V9 wrccr */ |
1106 |
|
case 0x3: /* V9 wrasi */ |
1107 |
|
case 0x6: /* V9 wrfprs */ |
1108 |
|
case 0xf: /* V9 sir */ |
1109 |
goto illegal_insn; |
goto illegal_insn; |
1110 |
} |
} |
1111 |
} |
} |
1112 |
break; |
break; |
1113 |
#if !defined(CONFIG_USER_ONLY) |
#if !defined(CONFIG_USER_ONLY) |
1114 |
case 0x31: |
case 0x31: /* wrpsr, V9 saved, restored */ |
1115 |
{ |
{ |
1116 |
if (!supervisor(dc)) |
if (!supervisor(dc)) |
1117 |
goto priv_insn; |
goto priv_insn; |
1119 |
gen_op_wrpsr(); |
gen_op_wrpsr(); |
1120 |
} |
} |
1121 |
break; |
break; |
1122 |
case 0x32: |
case 0x32: /* wrwim, V9 wrpr */ |
1123 |
{ |
{ |
1124 |
if (!supervisor(dc)) |
if (!supervisor(dc)) |
1125 |
goto priv_insn; |
goto priv_insn; |
1137 |
break; |
break; |
1138 |
#endif |
#endif |
1139 |
default: |
default: |
1140 |
|
case 0x2a: /* V9 rdpr */ |
1141 |
|
case 0x2b: /* V9 flushw */ |
1142 |
|
case 0x2c: /* V9 movcc */ |
1143 |
|
case 0x2d: /* V9 sdivx */ |
1144 |
|
case 0x2e: /* V9 popc */ |
1145 |
|
case 0x2f: /* V9 movr */ |
1146 |
goto illegal_insn; |
goto illegal_insn; |
1147 |
} |
} |
1148 |
} |
} |
1175 |
{ |
{ |
1176 |
gen_op_movl_npc_T0(); |
gen_op_movl_npc_T0(); |
1177 |
if (rd != 0) { |
if (rd != 0) { |
1178 |
gen_op_movl_T0_im((long) (dc->pc)); |
gen_op_movl_T0_im(dc->pc); |
1179 |
gen_movl_T0_reg(rd); |
gen_movl_T0_reg(rd); |
1180 |
} |
} |
1181 |
dc->pc = dc->npc; |
dc->pc = dc->npc; |
1183 |
} |
} |
1184 |
goto jmp_insn; |
goto jmp_insn; |
1185 |
#if !defined(CONFIG_USER_ONLY) |
#if !defined(CONFIG_USER_ONLY) |
1186 |
case 0x39: /* rett */ |
case 0x39: /* rett, V9 return */ |
1187 |
{ |
{ |
1188 |
if (!supervisor(dc)) |
if (!supervisor(dc)) |
1189 |
goto priv_insn; |
goto priv_insn; |
1206 |
gen_movl_T0_reg(rd); |
gen_movl_T0_reg(rd); |
1207 |
break; |
break; |
1208 |
default: |
default: |
1209 |
|
case 0x3e: /* V9 done/retry */ |
1210 |
goto illegal_insn; |
goto illegal_insn; |
1211 |
} |
} |
1212 |
} |
} |
1213 |
break; |
break; |
1214 |
} |
} |
1215 |
|
break; |
1216 |
case 3: /* load/store instructions */ |
case 3: /* load/store instructions */ |
1217 |
{ |
{ |
1218 |
unsigned int xop = GET_FIELD(insn, 7, 12); |
unsigned int xop = GET_FIELD(insn, 7, 12); |
1319 |
(void) &gen_op_lddfa; |
(void) &gen_op_lddfa; |
1320 |
#endif |
#endif |
1321 |
default: |
default: |
1322 |
|
case 0x08: /* V9 ldsw */ |
1323 |
|
case 0x0b: /* V9 ldx */ |
1324 |
|
case 0x18: /* V9 ldswa */ |
1325 |
|
case 0x1b: /* V9 ldxa */ |
1326 |
|
case 0x2d: /* V9 prefetch */ |
1327 |
|
case 0x30: /* V9 ldfa */ |
1328 |
|
case 0x33: /* V9 lddfa */ |
1329 |
|
case 0x3d: /* V9 prefetcha */ |
1330 |
|
|
1331 |
|
case 0x32: /* V9 ldqfa */ |
1332 |
goto illegal_insn; |
goto illegal_insn; |
1333 |
} |
} |
1334 |
gen_movl_T1_reg(rd); |
gen_movl_T1_reg(rd); |
1345 |
gen_op_ldfsr(); |
gen_op_ldfsr(); |
1346 |
gen_op_store_FT0_fpr(rd); |
gen_op_store_FT0_fpr(rd); |
1347 |
break; |
break; |
1348 |
|
case 0x22: /* load quad fpreg */ |
1349 |
|
goto nfpu_insn; |
1350 |
case 0x23: /* load double fpreg */ |
case 0x23: /* load double fpreg */ |
1351 |
gen_op_ldst(lddf); |
gen_op_ldst(lddf); |
1352 |
gen_op_store_DT0_fpr(rd); |
gen_op_store_DT0_fpr(rd); |
1396 |
break; |
break; |
1397 |
#endif |
#endif |
1398 |
default: |
default: |
1399 |
|
case 0x0e: /* V9 stx */ |
1400 |
|
case 0x1e: /* V9 stxa */ |
1401 |
goto illegal_insn; |
goto illegal_insn; |
1402 |
} |
} |
1403 |
} else if (xop > 0x23 && xop < 0x28) { |
} else if (xop > 0x23 && xop < 0x28) { |
1409 |
gen_op_load_fpr_FT0(rd); |
gen_op_load_fpr_FT0(rd); |
1410 |
gen_op_ldst(stf); |
gen_op_ldst(stf); |
1411 |
break; |
break; |
1412 |
case 0x25: |
case 0x25: /* stfsr, V9 stxfsr */ |
1413 |
gen_op_load_fpr_FT0(rd); |
gen_op_load_fpr_FT0(rd); |
1414 |
gen_op_stfsr(); |
gen_op_stfsr(); |
1415 |
break; |
break; |
1416 |
|
case 0x26: /* stdfq */ |
1417 |
|
goto nfpu_insn; |
1418 |
case 0x27: |
case 0x27: |
1419 |
gen_op_load_fpr_DT0(rd); |
gen_op_load_fpr_DT0(rd); |
1420 |
gen_op_ldst(stdf); |
gen_op_ldst(stdf); |
1421 |
break; |
break; |
|
case 0x26: /* stdfq */ |
|
1422 |
default: |
default: |
1423 |
|
case 0x34: /* V9 stfa */ |
1424 |
|
case 0x37: /* V9 stdfa */ |
1425 |
|
case 0x3c: /* V9 casa */ |
1426 |
|
case 0x3e: /* V9 casxa */ |
1427 |
|
|
1428 |
|
case 0x36: /* V9 stqfa */ |
1429 |
goto illegal_insn; |
goto illegal_insn; |
1430 |
} |
} |
1431 |
} else if (xop > 0x33 && xop < 0x38) { |
} else if (xop > 0x33 && xop < 0x38) { |
1435 |
else |
else |
1436 |
goto illegal_insn; |
goto illegal_insn; |
1437 |
} |
} |
1438 |
|
break; |
1439 |
} |
} |
1440 |
/* default case for non jump instructions */ |
/* default case for non jump instructions */ |
1441 |
if (dc->npc == DYNAMIC_PC) { |
if (dc->npc == DYNAMIC_PC) { |
1633 |
{ |
{ |
1634 |
int i, x; |
int i, x; |
1635 |
|
|
1636 |
cpu_fprintf(f, "pc: 0x%08x npc: 0x%08x\n", (int) env->pc, (int) env->npc); |
cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc, env->npc); |
1637 |
cpu_fprintf(f, "General Registers:\n"); |
cpu_fprintf(f, "General Registers:\n"); |
1638 |
for (i = 0; i < 4; i++) |
for (i = 0; i < 4; i++) |
1639 |
cpu_fprintf(f, "%%g%c: 0x%08x\t", i + '0', env->gregs[i]); |
cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]); |
1640 |
cpu_fprintf(f, "\n"); |
cpu_fprintf(f, "\n"); |
1641 |
for (; i < 8; i++) |
for (; i < 8; i++) |
1642 |
cpu_fprintf(f, "%%g%c: 0x%08x\t", i + '0', env->gregs[i]); |
cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]); |
1643 |
cpu_fprintf(f, "\nCurrent Register Window:\n"); |
cpu_fprintf(f, "\nCurrent Register Window:\n"); |
1644 |
for (x = 0; x < 3; x++) { |
for (x = 0; x < 3; x++) { |
1645 |
for (i = 0; i < 4; i++) |
for (i = 0; i < 4; i++) |
1646 |
cpu_fprintf(f, "%%%c%d: 0x%08x\t", |
cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t", |
1647 |
(x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i, |
(x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i, |
1648 |
env->regwptr[i + x * 8]); |
env->regwptr[i + x * 8]); |
1649 |
cpu_fprintf(f, "\n"); |
cpu_fprintf(f, "\n"); |
1650 |
for (; i < 8; i++) |
for (; i < 8; i++) |
1651 |
cpu_fprintf(f, "%%%c%d: 0x%08x\t", |
cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t", |
1652 |
(x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i, |
(x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i, |
1653 |
env->regwptr[i + x * 8]); |
env->regwptr[i + x * 8]); |
1654 |
cpu_fprintf(f, "\n"); |
cpu_fprintf(f, "\n"); |
1670 |
} |
} |
1671 |
|
|
1672 |
#if defined(CONFIG_USER_ONLY) |
#if defined(CONFIG_USER_ONLY) |
1673 |
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) |
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) |
1674 |
{ |
{ |
1675 |
return addr; |
return addr; |
1676 |
} |
} |
1677 |
|
|
1678 |
#else |
#else |
1679 |
extern int get_physical_address (CPUState *env, uint32_t *physical, int *prot, |
extern int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot, |
1680 |
int *access_index, uint32_t address, int rw, |
int *access_index, target_ulong address, int rw, |
1681 |
int is_user); |
int is_user); |
1682 |
|
|
1683 |
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) |
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) |
1684 |
{ |
{ |
1685 |
uint32_t phys_addr; |
target_phys_addr_t phys_addr; |
1686 |
int prot, access_index; |
int prot, access_index; |
1687 |
|
|
1688 |
if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0) |
if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0) |