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;
215 m_nr_of_valid_sfrs = 0;
216 if (m_model ==
"i960CA")
217 m_nr_of_valid_sfrs = 3;
227 " can not have bit 0 or 1 set!\n");
247 ss.flags(std::ios::hex);
248 ss <<
" ip = 0x" << std::setfill(
'0') << std::setw(8) << (uint32_t)
m_pc;
252 ss <<
" <" <<
symbol <<
">";
256 ss << std::setfill(
' ') << std::setw(4) << i960_regnames[i]
257 <<
" = 0x" << std::setfill(
'0') << std::setw(8) << m_r[i];
264 for (
size_t i = 0; i < m_nr_of_valid_sfrs; i++) {
267 ss << std::setfill(
' ') << std::setw(6) << name.str()
268 <<
" = 0x" << std::setfill(
'0') << std::setw(8) << m_sfr[i];
307 return instr_ToBeTranslated;
328 size_t instrSize =
sizeof(uint32_t);
329 uint32_t instructionWord;
337 const uint32_t iword = instructionWord;
339 const int opcode = iword >> 24;
341 const int REG_src_dst = (iword >> 19) & 0x1f;
342 const int REG_src2 = (iword >> 14) & 0x1f;
343 const int REG_m3 = (iword >> 13) & 0x1;
344 const int REG_m2 = (iword >> 12) & 0x1;
345 const int REG_m1 = (iword >> 11) & 0x1;
346 const int REG_opcode2 = (iword >> 7) & 0xf;
347 const int REG_sfr2 = (iword >> 6) & 0x1;
348 const int REG_sfr1 = (iword >> 5) & 0x1;
349 const int REG_src1 = (iword >> 0) & 0x1f;
351 const int COBR_src_dst = (iword >> 19) & 0x1f;
352 const int COBR_src_2 = (iword >> 14) & 0x1f;
353 const int COBR_m1 = (iword >> 13) & 0x1;
354 const int COBR_disp = (iword >> 2) & 0x7ff;
355 const int COBR_t = (iword >> 1) & 0x1;
356 const int COBR_s2 = (iword >> 0) & 0x1;
358 const int CTRL_disp = (iword >> 2) & 0x3fffff;
359 const int CTRL_t = (iword >> 1) & 0x1;
362 const int MEMA_abase = (iword >> 14) & 0x1f;
363 const int MEMA_md = (iword >> 13) & 0x1;
365 const int MEMA_offset = (iword >> 0) & 0xfff;
367 const int MEMB_src_dst = (iword >> 19) & 0x1f;
368 const int MEMB_abase = (iword >> 14) & 0x1f;
369 const int MEMB_mode = (iword >> 10) & 0xf;
370 const int MEMB_scale = (iword >> 7) & 0x7;
372 const int MEMB_index = (iword >> 0) & 0x1f;
374 bool hasDisplacementWord =
false;
376 if (
opcode >= 0x80 && iword & 0x1000) {
378 int mode = (iword >> 10) & 0xf;
379 if (mode == 0x5 || mode >= 0xc)
380 hasDisplacementWord =
true;
383 uint32_t displacementWord = 0;
384 if (hasDisplacementWord) {
385 instrSize +=
sizeof(uint32_t);
396 ssHex.flags(std::ios::hex);
397 ssHex << std::setfill(
'0') << std::setw(8) << (uint32_t) iword;
398 if (hasDisplacementWord)
399 ssHex <<
" " << std::setfill(
'0') << std::setw(8) << (uint32_t) displacementWord;
403 result.push_back(ssHex.str());
406 stringstream ssOpcode;
408 stringstream ssComments;
412 const char* mnemonics[] = {
439 ssOpcode << mnemonics[
opcode - 0x08];
444 if (hasDisplacement) {
445 uint32_t disp = CTRL_disp << 2;
446 if (disp & 0x00800000)
449 uint32_t
addr = vaddr + disp;
451 ssArgs.flags(std::ios::hex);
452 ssArgs << std::setfill(
'0') << std::setw(8) <<
addr;
456 const char* mnemonics[] = {
494 ssOpcode << mnemonics[
opcode - 0x20];
501 ssArgs << regname_or_literal(COBR_src_dst, 0, COBR_s2);
503 uint32_t targ = COBR_disp << 2;
504 if (targ & 0x00001000)
508 ssArgs << regname_or_literal(COBR_src_dst, src1isBitpos ? 1 : COBR_m1, 0) <<
",";
509 ssArgs << regname_or_literal(COBR_src_2, 0, COBR_s2) <<
",";
511 ssArgs.flags(std::ios::hex);
512 ssArgs << std::setfill(
'0') << std::setw(8) << targ;
517 for (
int i = 0; ; ++i) {
528 if (rinstr == NULL) {
529 ssOpcode <<
"unknown_reg_";
530 ssOpcode.flags(std::ios::hex);
531 ssOpcode << std::setfill(
'0') << std::setw(2) <<
opcode;
532 ssOpcode <<
":" << std::setw(1) << REG_opcode2;
542 ssArgs << regname_or_literal(REG_src1, REG_m1, REG_sfr1);
545 if (ssArgs.str().length() > 0)
547 ssArgs << regname_or_literal(REG_src2, REG_m2, REG_sfr2);
551 if (ssArgs.str().length() > 0)
565 ssArgs << regname_or_literal(REG_src_dst, 1, 0);
567 ssArgs << regname_or_literal(REG_src_dst, 0, 1);
569 ssArgs << regname_or_literal(REG_src_dst, 0, 0);
578 const char* mnemonics[] = {
680 ssOpcode << mnemonics[
opcode - 0x80];
683 bool isStore = !!(
opcode & 2);
685 if (usesDst && isStore) {
686 ssArgs << regname_or_literal(MEMB_src_dst, 0, 0) <<
",";
689 if (iword & 0x1000) {
691 int scale = 1 << MEMB_scale;
694 ssArgs <<
"(" << regname_or_literal(MEMB_abase, 0, 0) <<
")";
698 uint32_t offset = displacementWord + 8;
700 ssArgs.flags(std::ios::hex);
701 ssArgs << std::setfill(
'0') << std::setw(8) << offset;
707 ssArgs <<
"(" << regname_or_literal(MEMB_abase, 0, 0) <<
")";
708 ssArgs <<
"[" << regname_or_literal(MEMB_index, 0, 0) <<
"*" << scale <<
"]";
713 uint32_t offset = displacementWord;
715 ssArgs.flags(std::ios::hex);
716 ssArgs << std::setfill(
'0') << std::setw(8) << offset;
717 if (MEMB_mode == 0xd)
718 ssArgs <<
"(" << regname_or_literal(MEMB_abase, 0, 0) <<
")";
724 uint32_t offset = displacementWord;
726 ssArgs.flags(std::ios::hex);
727 ssArgs << std::setfill(
'0') << std::setw(8) << offset;
728 if (MEMB_mode == 0xf)
729 ssArgs <<
"(" << regname_or_literal(MEMB_abase, 0, 0) <<
")";
730 ssArgs <<
"[" << regname_or_literal(MEMB_index, 0, 0) <<
"*" << scale <<
"]";
734 ssArgs <<
"unimplemented MEMB mode!";
739 ssArgs.flags(std::ios::hex);
740 ssArgs << std::setfill(
'0') << std::setw(1) << MEMA_offset;
743 ssArgs <<
"(" << regname_or_literal(MEMA_abase, 0, 0) <<
")";
746 if (usesDst && !isStore) {
747 ssArgs <<
"," << regname_or_literal(MEMB_src_dst, 0, 0);
749 }
else if (iword == 0) {
752 ssOpcode <<
"unknown_0x";
753 ssOpcode.flags(std::ios::hex);
754 ssOpcode << std::setfill(
'0') << std::setw(2) << (int)
opcode;
757 result.push_back(ssOpcode.str());
758 result.push_back(ssArgs.str());
759 string comments = ssComments.str();
760 if (comments.length() > 0)
761 result.push_back(comments);
769 if (attributeName ==
"description")
770 return "Intel i960 processor.";
782 cpu->m_pc =
ic->arg[0].u32;
783 cpu->DyntransPCtoPointers();
791 cpu->m_nextIC =
ic + 2;
811 uint32_t message =
REG32(
ic->arg[0]);
812 int type = (message >> 8) & 0xff;
813 int field1 = message & 0xff;
824 UI* ui =
cpu->GetUI();
826 }
else if (type == 0x04) {
829 UI* ui =
cpu->GetUI();
831 ss <<
"TODO: load control register, group " << field1;
837 cpu->m_executedCycles --;
843 cpu->m_nextIC = &
cpu->m_abortIC;
845 UI* ui =
cpu->GetUI();
846 ss <<
"unimplemented sysctl message type " << type;
855 void I960_CPUComponent::Translate(uint32_t iword, uint32_t iword2,
struct DyntransIC*
ic)
859 unsigned int opcode = iword >> 24;
863 const int CTRL_disp = (iword >> 2) & 0x3fffff;
864 uint32_t disp = CTRL_disp << 2;
865 if (disp & 0x00800000)
868 ic->arg[0].u32 = disp +
m_pc;
875 const int REG_src_dst = (iword >> 19) & 0x1f;
876 const int REG_src2 = (iword >> 14) & 0x1f;
877 const int REG_m3 = (iword >> 13) & 0x1;
878 const int REG_m2 = (iword >> 12) & 0x1;
879 const int REG_m1 = (iword >> 11) & 0x1;
880 const int REG_opcode2 = (iword >> 7) & 0xf;
881 const int REG_s2 = (iword >> 6) & 0x1;
882 const int REG_s1 = (iword >> 5) & 0x1;
883 const int REG_src1 = (iword >> 0) & 0x1f;
885 int op3 = (
opcode << 4) + REG_opcode2;
888 ic->arg[0].u32 = REG_src1;
891 ic->arg[0].p = &m_sfr[REG_src1];
893 ic->arg[0].p = &m_r[REG_src1];
897 ic->arg[1].u32 = REG_src2;
900 ic->arg[1].p = &m_sfr[REG_src1];
902 ic->arg[1].p = &m_r[REG_src2];
911 ic->arg[2].p = &m_r[REG_src_dst];
921 f_lit_lit_reg = instr_mov_lit_reg;
922 f_lit_reg_reg = instr_mov_lit_reg;
923 f_reg_lit_reg = instr_mov_reg_reg;
924 }
else if (op3 == 0x659) {
926 f_reg_reg_reg = instr_sysctl;
930 if (REG_m1 && REG_m2)
931 ic->f = f_lit_lit_reg;
932 if (REG_m1 && !REG_m2)
933 ic->f = f_lit_reg_reg;
934 if (!REG_m1 && REG_m2)
935 ic->f = f_reg_lit_reg;
936 if (!REG_m1 && !REG_m2)
937 ic->f = f_reg_reg_reg;
942 }
else if (opcode >= 0x80 && opcode <= 0xcf) {
945 const int MEMA_md = (iword >> 13) & 0x1;
946 const int MEMA_offset = (iword >> 0) & 0xfff;
947 const int MEMB_src_dst = (iword >> 19) & 0x1f;
949 const int MEMB_mode = (iword >> 10) & 0xf;
953 ic->arg[2].p = &m_r[MEMB_src_dst];
955 if (iword & 0x1000) {
959 ic->arg[0].u32 = iword2;
960 ic->f = instr_lda_displacement;
970 ic->arg[0].u32 = MEMA_offset;
971 ic->f = instr_mov_lit_reg;
976 if (
ic->f == NULL && ui != NULL) {
978 ss.flags(std::ios::hex);
979 ss <<
"unimplemented opcode 0x" << opcode;
980 if (opcode >= 0x58 && opcode <= 0x7f)
981 ss <<
",0x" << ((iword >> 7) & 0xf);
991 cpu->DyntransToBeTranslatedBegin(
ic);
994 if (
cpu->DyntransReadInstruction(iword)) {
995 bool readCompleteInstruction =
true;
997 uint32_t opcode = iword >> 24;
998 if (opcode >= 0x80 && opcode <= 0xcf) {
1000 int mode = (iword >> 10) & 0xf;
1001 if (mode == 0x5 || mode >= 0xc)
1002 readCompleteInstruction =
cpu->DyntransReadInstruction(iword2, 4);
1003 if (!readCompleteInstruction) {
1004 UI* ui =
cpu->GetUI();
1009 if (readCompleteInstruction)
1010 cpu->Translate(iword, iword2,
ic);
1013 cpu->DyntransToBeTranslatedDone(
ic);
1020 #ifdef WITHUNITTESTS
1024 static void Test_I960_CPUComponent_Create()
1033 static GXemul SimpleMachine()
1044 static void Test_I960_CPUComponent_Disassembly_Basic()
1046 GXemul gxemul = SimpleMachine();
1051 vector<string> result;
1060 len =
cpu->DisassembleInstruction(0x3fe00048, result);
1069 static void Test_I960_CPUComponent_Execute_mov()
1071 GXemul gxemul = SimpleMachine();
1080 cpu->SetVariableValue(
"pc",
"0x3fe00048");
1081 cpu->SetVariableValue(
"r4",
"0x1234");
1086 UnitTest::Assert(
"pc should have increased",
cpu->GetVariable(
"pc")->ToInteger(), 0x3fe0004c);
1089 cpu->SetVariableValue(
"r4",
"0x12345");
1094 UnitTest::Assert(
"pc should have increased again",
cpu->GetVariable(
"pc")->ToInteger(), 0x3fe00050);
1095 UnitTest::Assert(
"r4 should have been modified again",
cpu->GetVariable(
"r4")->ToInteger(), 6);
1098 static void Test_I960_CPUComponent_Execute_b()
1100 GXemul gxemul = SimpleMachine();
1107 cpu->SetVariableValue(
"pc",
"0x3fe00004");
1112 UnitTest::Assert(
"pc should have changed",
cpu->GetVariable(
"pc")->ToInteger(), 0x3fe006c4);
1114 cpu->SetVariableValue(
"pc",
"0x3fe00004");
1119 UnitTest::Assert(
"pc should have changed again",
cpu->GetVariable(
"pc")->ToInteger(), 0x3fe006c4);
1122 static void Test_I960_CPUComponent_Execute_lda_with_offset()
1124 GXemul gxemul = SimpleMachine();
1131 cpu->SetVariableValue(
"pc",
"0x3fe00010");
1138 static void Test_I960_CPUComponent_Execute_lda_with_displacement()
1140 GXemul gxemul = SimpleMachine();
1149 cpu->SetVariableValue(
"pc",
"0x3fe00010");
1158 UNITTEST(Test_I960_CPUComponent_Create);
1159 UNITTEST(Test_I960_CPUComponent_Disassembly_Basic);
1161 UNITTEST(Test_I960_CPUComponent_Execute_mov);
1162 UNITTEST(Test_I960_CPUComponent_Execute_b);
1163 UNITTEST(Test_I960_CPUComponent_Execute_lda_with_offset);
1164 UNITTEST(Test_I960_CPUComponent_Execute_lda_with_displacement);