48 { 0x580,
"notbit",
true,
true,
true,
false },
49 { 0x581,
"and",
true,
true,
true,
false },
50 { 0x582,
"andnot",
true,
true,
true,
false },
51 { 0x583,
"setbit",
true,
true,
true,
false },
52 { 0x584,
"notand",
true,
true,
true,
false },
53 { 0x586,
"xor",
true,
true,
true,
false },
54 { 0x587,
"or",
true,
true,
true,
false },
55 { 0x588,
"nor",
true,
true,
true,
false },
56 { 0x589,
"xnor",
true,
true,
true,
false },
57 { 0x58a,
"not",
true,
false,
true,
false },
58 { 0x58b,
"ornot",
true,
true,
true,
false },
59 { 0x58c,
"clrbit",
true,
true,
true,
false },
60 { 0x58d,
"notor",
true,
true,
true,
false },
61 { 0x58e,
"nand",
true,
true,
true,
false },
62 { 0x58f,
"alterbit",
true,
true,
true,
false },
64 { 0x590,
"addo",
true,
true,
true,
false },
65 { 0x591,
"addi",
true,
true,
true,
false },
66 { 0x592,
"subo",
true,
true,
true,
false },
67 { 0x593,
"subi",
true,
true,
true,
false },
68 { 0x598,
"shro",
true,
true,
true,
false },
69 { 0x59a,
"shrdi",
true,
true,
true,
false },
70 { 0x59b,
"shri" ,
true,
true,
true,
false },
71 { 0x59c,
"shlo",
true,
true,
true,
false },
72 { 0x59d,
"rotate",
true,
true,
true,
false },
73 { 0x59e,
"shli",
true,
true,
true,
false },
75 { 0x5a0,
"cmpo",
true,
true,
false,
false },
76 { 0x5a1,
"cmpi",
true,
true,
false,
false },
77 { 0x5a2,
"concmpo",
true,
true,
false,
false },
78 { 0x5a3,
"concmpi",
true,
true,
false,
false },
79 { 0x5a4,
"cmpinco",
true,
true,
true,
false },
80 { 0x5a5,
"cmpinci",
true,
true,
true,
false },
81 { 0x5a6,
"cmpdeco",
true,
true,
true,
false },
82 { 0x5a7,
"cmpdeci",
true,
true,
true,
false },
84 { 0x5ac,
"scanbyte",
true,
true,
false,
false },
85 { 0x5ae,
"chkbit",
true,
true,
false,
false },
87 { 0x5b0,
"addc",
true,
true,
true,
false },
88 { 0x5b2,
"subc",
true,
true,
true,
false },
90 { 0x5cc,
"mov",
true,
false,
true,
false },
91 { 0x5d8,
"eshro",
true,
true,
true,
false },
92 { 0x5dc,
"movl",
true,
false,
true,
false },
93 { 0x5ec,
"movt",
true,
false,
true,
false },
94 { 0x5fc,
"movq",
true,
false,
true,
false },
96 { 0x630,
"sdma",
true,
true,
true,
true },
97 { 0x631,
"udma",
false,
false,
false,
false },
99 { 0x640,
"spanbit",
true,
false,
true,
false },
100 { 0x641,
"scanbit",
true,
false,
true,
false },
101 { 0x645,
"modac",
true,
true,
true,
true },
103 { 0x650,
"modify",
true,
true,
true,
true },
104 { 0x651,
"extract",
true,
true,
true,
true },
105 { 0x654,
"modtc",
true,
true,
true,
true },
106 { 0x655,
"modpc",
true,
true,
true,
true },
107 { 0x659,
"sysctl",
true,
true,
true,
true },
109 { 0x660,
"calls",
true,
false,
false,
false },
110 { 0x66b,
"mark",
false,
false,
false,
false },
111 { 0x66c,
"fmark",
false,
false,
false,
false },
112 { 0x66d,
"flushreg",
false,
false,
false,
false },
113 { 0x66f,
"syncf",
false,
false,
false,
false },
115 { 0x670,
"emul",
true,
true,
true,
false },
116 { 0x671,
"ediv",
true,
true,
true,
false },
118 { 0x701,
"mulo",
true,
true,
true,
false },
119 { 0x708,
"remo",
true,
true,
true,
false },
120 { 0x70b,
"divo",
true,
true,
true,
false },
122 { 0x741,
"muli",
true,
true,
true,
false },
123 { 0x748,
"remi",
true,
true,
true,
false },
124 { 0x749,
"modi",
true,
true,
true,
false },
125 { 0x74b,
"divi",
true,
true,
true,
false },
127 { 0, NULL,
false,
false,
false,
false }
155 AddVariable(
"nr_of_valid_sfrs", &m_nr_of_valid_sfrs);
169 if (!
cpu->SetVariableValue(
"model",
"\"" +
settings[
"model"] +
"\""))
176 static string regname_or_literal(
int reg,
int m,
int s)
179 if (m == 0 && s == 0)
180 return i960_regnames[
reg];
184 if (m != 0 && s == 0) {
187 }
else if (m == 0 && s != 0) {
191 ss <<
"reserved" <<
reg;
211 m_nr_of_valid_sfrs = 0;
212 if (m_model ==
"i960CA")
213 m_nr_of_valid_sfrs = 3;
223 " can not have bit 0 or 1 set!\n");
243 ss.flags(std::ios::hex);
244 ss <<
" ip = 0x" << std::setfill(
'0') << std::setw(8) << (uint32_t)
m_pc;
248 ss <<
" <" <<
symbol <<
">";
252 ss << std::setfill(
' ') << std::setw(4) << i960_regnames[i]
253 <<
" = 0x" << std::setfill(
'0') << std::setw(8) << m_r[i];
260 for (
size_t i = 0; i < m_nr_of_valid_sfrs; i++) {
263 ss << std::setfill(
' ') << std::setw(6) << name.str()
264 <<
" = 0x" << std::setfill(
'0') << std::setw(8) << m_sfr[i];
303 return instr_ToBeTranslated;
323 unsigned char *instruction, vector<string>& result)
325 size_t instrSize =
sizeof(uint32_t);
327 if (maxLen < instrSize) {
333 uint32_t instructionWord = ((uint32_t *) (
void *) instruction)[0];
339 const uint32_t iword = instructionWord;
341 const int opcode = iword >> 24;
343 const int REG_src_dst = (iword >> 19) & 0x1f;
344 const int REG_src2 = (iword >> 14) & 0x1f;
345 const int REG_m3 = (iword >> 13) & 0x1;
346 const int REG_m2 = (iword >> 12) & 0x1;
347 const int REG_m1 = (iword >> 11) & 0x1;
348 const int REG_opcode2 = (iword >> 7) & 0xf;
349 const int REG_sfr2 = (iword >> 6) & 0x1;
350 const int REG_sfr1 = (iword >> 5) & 0x1;
351 const int REG_src1 = (iword >> 0) & 0x1f;
353 const int COBR_src_dst = (iword >> 19) & 0x1f;
354 const int COBR_src_2 = (iword >> 14) & 0x1f;
355 const int COBR_m1 = (iword >> 13) & 0x1;
356 const int COBR_disp = (iword >> 2) & 0x7ff;
357 const int COBR_t = (iword >> 1) & 0x1;
358 const int COBR_s2 = (iword >> 0) & 0x1;
360 const int CTRL_disp = (iword >> 2) & 0x3fffff;
361 const int CTRL_t = (iword >> 1) & 0x1;
364 const int MEMA_abase = (iword >> 14) & 0x1f;
365 const int MEMA_md = (iword >> 13) & 0x1;
367 const int MEMA_offset = (iword >> 0) & 0xfff;
369 const int MEMB_src_dst = (iword >> 19) & 0x1f;
370 const int MEMB_abase = (iword >> 14) & 0x1f;
371 const int MEMB_mode = (iword >> 10) & 0xf;
372 const int MEMB_scale = (iword >> 7) & 0x7;
374 const int MEMB_index = (iword >> 0) & 0x1f;
376 bool hasDisplacementWord =
false;
378 if (
opcode >= 0x80 && iword & 0x1000) {
380 int mode = (iword >> 10) & 0xf;
381 if (mode == 0x5 || mode >= 0xc)
382 hasDisplacementWord =
true;
385 uint32_t displacementWord = 0;
386 if (hasDisplacementWord) {
387 instrSize +=
sizeof(uint32_t);
388 if (maxLen < instrSize)
391 displacementWord = ((uint32_t *) (
void *) instruction)[1];
399 ssHex.flags(std::ios::hex);
400 ssHex << std::setfill(
'0') << std::setw(8) << (uint32_t) iword;
401 if (hasDisplacementWord)
402 ssHex <<
" " << std::setfill(
'0') << std::setw(8) << (uint32_t) displacementWord;
406 result.push_back(ssHex.str());
409 stringstream ssOpcode;
411 stringstream ssComments;
415 const char* mnemonics[] = {
442 ssOpcode << mnemonics[
opcode - 0x08];
447 if (hasDisplacement) {
448 uint32_t disp = CTRL_disp << 2;
449 if (disp & 0x00800000)
452 uint32_t
addr = vaddr + disp;
454 ssArgs.flags(std::ios::hex);
455 ssArgs << std::setfill(
'0') << std::setw(8) <<
addr;
459 const char* mnemonics[] = {
497 ssOpcode << mnemonics[
opcode - 0x20];
504 ssArgs << regname_or_literal(COBR_src_dst, 0, COBR_s2);
506 uint32_t targ = COBR_disp << 2;
507 if (targ & 0x00001000)
511 ssArgs << regname_or_literal(COBR_src_dst, src1isBitpos ? 1 : COBR_m1, 0) <<
",";
512 ssArgs << regname_or_literal(COBR_src_2, 0, COBR_s2) <<
",";
514 ssArgs.flags(std::ios::hex);
515 ssArgs << std::setfill(
'0') << std::setw(8) << targ;
520 for (
int i = 0; ; ++i) {
531 if (rinstr == NULL) {
532 ssOpcode <<
"unknown_reg_";
533 ssOpcode.flags(std::ios::hex);
534 ssOpcode << std::setfill(
'0') << std::setw(2) <<
opcode;
535 ssOpcode <<
":" << std::setw(1) << REG_opcode2;
545 ssArgs << regname_or_literal(REG_src1, REG_m1, REG_sfr1);
548 if (ssArgs.str().length() > 0)
550 ssArgs << regname_or_literal(REG_src2, REG_m2, REG_sfr2);
554 if (ssArgs.str().length() > 0)
568 ssArgs << regname_or_literal(REG_src_dst, 1, 0);
570 ssArgs << regname_or_literal(REG_src_dst, 0, 1);
572 ssArgs << regname_or_literal(REG_src_dst, 0, 0);
581 const char* mnemonics[] = {
683 ssOpcode << mnemonics[
opcode - 0x80];
686 bool isStore = !!(
opcode & 2);
688 if (usesDst && isStore) {
689 ssArgs << regname_or_literal(MEMB_src_dst, 0, 0) <<
",";
692 if (iword & 0x1000) {
694 int scale = 1 << MEMB_scale;
697 ssArgs <<
"(" << regname_or_literal(MEMB_abase, 0, 0) <<
")";
701 uint32_t offset = displacementWord + 8;
703 ssArgs.flags(std::ios::hex);
704 ssArgs << std::setfill(
'0') << std::setw(8) << offset;
710 ssArgs <<
"(" << regname_or_literal(MEMB_abase, 0, 0) <<
")";
711 ssArgs <<
"[" << regname_or_literal(MEMB_index, 0, 0) <<
"*" << scale <<
"]";
716 uint32_t offset = displacementWord;
718 ssArgs.flags(std::ios::hex);
719 ssArgs << std::setfill(
'0') << std::setw(8) << offset;
720 if (MEMB_mode == 0xd)
721 ssArgs <<
"(" << regname_or_literal(MEMB_abase, 0, 0) <<
")";
727 uint32_t offset = displacementWord;
729 ssArgs.flags(std::ios::hex);
730 ssArgs << std::setfill(
'0') << std::setw(8) << offset;
731 if (MEMB_mode == 0xf)
732 ssArgs <<
"(" << regname_or_literal(MEMB_abase, 0, 0) <<
")";
733 ssArgs <<
"[" << regname_or_literal(MEMB_index, 0, 0) <<
"*" << scale <<
"]";
737 ssArgs <<
"unimplemented MEMB mode!";
742 ssArgs.flags(std::ios::hex);
743 ssArgs << std::setfill(
'0') << std::setw(1) << MEMA_offset;
746 ssArgs <<
"(" << regname_or_literal(MEMA_abase, 0, 0) <<
")";
749 if (usesDst && !isStore) {
750 ssArgs <<
"," << regname_or_literal(MEMB_src_dst, 0, 0);
752 }
else if (iword == 0) {
755 ssOpcode <<
"unknown_0x";
756 ssOpcode.flags(std::ios::hex);
757 ssOpcode << std::setfill(
'0') << std::setw(2) << (int)
opcode;
760 result.push_back(ssOpcode.str());
761 result.push_back(ssArgs.str());
762 string comments = ssComments.str();
763 if (comments.length() > 0)
764 result.push_back(comments);
772 if (attributeName ==
"stable")
775 if (attributeName ==
"description")
776 return "Intel i960 processor.";
788 cpu->m_pc =
ic->arg[0].u32;
789 cpu->DyntransPCtoPointers();
797 cpu->m_nextIC =
ic + 2;
811 uint32_t message =
REG32(
ic->arg[0]);
812 int type = (message >> 8) & 0xff;
817 UI* ui =
cpu->GetUI();
822 cpu->m_executedCycles --;
828 cpu->m_nextIC = &
cpu->m_abortIC;
830 UI* ui =
cpu->GetUI();
839 void I960_CPUComponent::Translate(uint32_t iword, uint32_t iword2,
struct DyntransIC*
ic)
843 unsigned int opcode = iword >> 24;
847 const int CTRL_disp = (iword >> 2) & 0x3fffff;
848 uint32_t disp = CTRL_disp << 2;
849 if (disp & 0x00800000)
852 ic->arg[0].u32 = disp +
m_pc;
859 const int REG_src_dst = (iword >> 19) & 0x1f;
860 const int REG_src2 = (iword >> 14) & 0x1f;
861 const int REG_m3 = (iword >> 13) & 0x1;
862 const int REG_m2 = (iword >> 12) & 0x1;
863 const int REG_m1 = (iword >> 11) & 0x1;
864 const int REG_opcode2 = (iword >> 7) & 0xf;
865 const int REG_s2 = (iword >> 6) & 0x1;
866 const int REG_s1 = (iword >> 5) & 0x1;
867 const int REG_src1 = (iword >> 0) & 0x1f;
869 int op3 = (
opcode << 4) + REG_opcode2;
872 ic->arg[0].u32 = REG_src1;
875 ic->arg[0].p = &m_sfr[REG_src1];
877 ic->arg[0].p = &m_r[REG_src1];
881 ic->arg[1].u32 = REG_src2;
884 ic->arg[1].p = &m_sfr[REG_src1];
886 ic->arg[1].p = &m_r[REG_src2];
895 ic->arg[2].p = &m_r[REG_src_dst];
905 f_lit_lit_reg = instr_mov_lit_reg;
906 f_lit_reg_reg = instr_mov_lit_reg;
907 }
else if (op3 == 0x659) {
909 f_reg_reg_reg = instr_sysctl;
913 if (REG_m1 && REG_m2)
914 ic->f = f_lit_lit_reg;
915 if (REG_m1 && !REG_m2)
916 ic->f = f_lit_reg_reg;
917 if (!REG_m1 && REG_m2)
918 ic->f = f_reg_lit_reg;
919 if (!REG_m1 && !REG_m2)
920 ic->f = f_reg_reg_reg;
925 }
else if (opcode >= 0x80 && opcode <= 0xcf) {
928 const int MEMA_md = (iword >> 13) & 0x1;
929 const int MEMA_offset = (iword >> 0) & 0xfff;
930 const int MEMB_src_dst = (iword >> 19) & 0x1f;
932 const int MEMB_mode = (iword >> 10) & 0xf;
936 ic->arg[2].p = &m_r[MEMB_src_dst];
938 if (iword & 0x1000) {
942 ic->arg[0].u32 = iword2;
943 ic->f = instr_lda_displacement;
953 ic->arg[0].u32 = MEMA_offset;
954 ic->f = instr_mov_lit_reg;
959 if (
ic->f == NULL && ui != NULL) {
961 ss.flags(std::ios::hex);
962 ss <<
"unimplemented opcode 0x" << opcode;
972 cpu->DyntransToBeTranslatedBegin(
ic);
975 if (
cpu->DyntransReadInstruction(iword)) {
976 bool readCompleteInstruction =
true;
978 uint32_t opcode = iword >> 24;
979 if (opcode >= 0x80 && opcode <= 0xcf) {
981 int mode = (iword >> 10) & 0xf;
982 if (mode == 0x5 || mode >= 0xc)
983 readCompleteInstruction =
cpu->DyntransReadInstruction(iword2, 4);
984 if (!readCompleteInstruction) {
985 UI* ui =
cpu->GetUI();
990 if (readCompleteInstruction)
991 cpu->Translate(iword, iword2,
ic);
994 cpu->DyntransToBeTranslatedDone(
ic);
1001 #ifdef WITHUNITTESTS
1005 static void Test_I960_CPUComponent_Create()
1014 static void Test_I960_CPUComponent_Disassembly_Basic()
1019 vector<string> result;
1021 unsigned char instruction[
sizeof(uint32_t) * 2];
1024 instruction[0] = 0x00;
1025 instruction[1] = 0x30;
1026 instruction[2] = 0x68;
1027 instruction[3] = 0x8c;
1029 instruction[4] = 0x01;
1030 instruction[5] = 0x23;
1031 instruction[6] = 0x34;
1032 instruction[7] = 0x45;
1034 len =
cpu->DisassembleInstruction(0x12345678,
sizeof(instruction), instruction, result);
1043 static GXemul SimpleMachine()
1054 static void Test_I960_CPUComponent_Execute_mov()
1056 GXemul gxemul = SimpleMachine();
1065 cpu->SetVariableValue(
"pc",
"0x3fe00048");
1066 cpu->SetVariableValue(
"r4",
"0x1234");
1071 UnitTest::Assert(
"pc should have increased",
cpu->GetVariable(
"pc")->ToInteger(), 0x3fe0004c);
1074 cpu->SetVariableValue(
"r4",
"0x12345");
1079 UnitTest::Assert(
"pc should have increased again",
cpu->GetVariable(
"pc")->ToInteger(), 0x3fe00050);
1080 UnitTest::Assert(
"r4 should have been modified again",
cpu->GetVariable(
"r4")->ToInteger(), 6);
1083 static void Test_I960_CPUComponent_Execute_b()
1085 GXemul gxemul = SimpleMachine();
1092 cpu->SetVariableValue(
"pc",
"0x3fe00004");
1097 UnitTest::Assert(
"pc should have changed",
cpu->GetVariable(
"pc")->ToInteger(), 0x3fe006c4);
1099 cpu->SetVariableValue(
"pc",
"0x3fe00004");
1104 UnitTest::Assert(
"pc should have changed again",
cpu->GetVariable(
"pc")->ToInteger(), 0x3fe006c4);
1107 static void Test_I960_CPUComponent_Execute_lda_with_offset()
1109 GXemul gxemul = SimpleMachine();
1116 cpu->SetVariableValue(
"pc",
"0x3fe00010");
1123 static void Test_I960_CPUComponent_Execute_lda_with_displacement()
1125 GXemul gxemul = SimpleMachine();
1134 cpu->SetVariableValue(
"pc",
"0x3fe00010");
1143 UNITTEST(Test_I960_CPUComponent_Create);
1144 UNITTEST(Test_I960_CPUComponent_Disassembly_Basic);
1146 UNITTEST(Test_I960_CPUComponent_Execute_mov);
1147 UNITTEST(Test_I960_CPUComponent_Execute_b);
1148 UNITTEST(Test_I960_CPUComponent_Execute_lda_with_offset);
1149 UNITTEST(Test_I960_CPUComponent_Execute_lda_with_displacement);