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);
163 settings[
"model"] =
"i960CA";
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;
405 result.push_back(ssHex.str());
408 stringstream ssOpcode;
410 stringstream ssComments;
412 if (opcode >= 0x08 && opcode <= 0x1f) {
414 const char* mnemonics[] = {
441 ssOpcode << mnemonics[opcode - 0x08];
445 bool hasDisplacement = opcode < 0x18 && opcode != 0x0a;
446 if (hasDisplacement) {
447 uint32_t disp = CTRL_disp << 2;
448 if (disp & 0x00800000)
451 uint32_t
addr = vaddr + disp;
453 ssArgs.flags(std::ios::hex);
454 ssArgs << std::setfill(
'0') << std::setw(8) <<
addr;
456 }
else if (opcode >= 0x20 && opcode <= 0x3f) {
458 const char* mnemonics[] = {
496 ssOpcode << mnemonics[opcode - 0x20];
500 bool src1isBitpos = opcode == 0x30 || opcode == 0x37;
502 if (opcode <= 0x27) {
503 ssArgs << regname_or_literal(COBR_src_dst, 0, COBR_s2);
505 uint32_t targ = COBR_disp << 2;
506 if (targ & 0x00001000)
510 ssArgs << regname_or_literal(COBR_src_dst, src1isBitpos ? 1 : COBR_m1, 0) <<
",";
511 ssArgs << regname_or_literal(COBR_src_2, 0, COBR_s2) <<
",";
513 ssArgs.flags(std::ios::hex);
514 ssArgs << std::setfill(
'0') << std::setw(8) << targ;
516 }
else if (opcode >= 0x58 && opcode <= 0x7f) {
519 for (
int i = 0; ; ++i) {
520 if (reg_instructions[i].
mnemonic == NULL)
522 if (reg_instructions[i].opcode == (opcode << 4) + REG_opcode2) {
523 rinstr = ®_instructions[i];
530 if (rinstr == NULL) {
531 ssOpcode <<
"unknown_reg_";
532 ssOpcode.flags(std::ios::hex);
533 ssOpcode << std::setfill(
'0') << std::setw(2) <<
opcode;
534 ssOpcode <<
":" << std::setw(1) << REG_opcode2;
544 ssArgs << regname_or_literal(REG_src1, REG_m1, REG_sfr1);
547 if (ssArgs.str().length() > 0)
549 ssArgs << regname_or_literal(REG_src2, REG_m2, REG_sfr2);
553 if (ssArgs.str().length() > 0)
567 ssArgs << regname_or_literal(REG_src_dst, 1, 0);
569 ssArgs << regname_or_literal(REG_src_dst, 0, 1);
571 ssArgs << regname_or_literal(REG_src_dst, 0, 0);
573 }
else if (opcode >= 0x80 && opcode <= 0xcf) {
580 const char* mnemonics[] = {
682 ssOpcode << mnemonics[opcode - 0x80];
684 bool usesDst = opcode != 0x84 && opcode != 0x86;
685 bool isStore = !!(opcode & 2);
687 if (usesDst && isStore) {
688 ssArgs << regname_or_literal(MEMB_src_dst, 0, 0) <<
",";
691 if (iword & 0x1000) {
693 int scale = 1 << MEMB_scale;
696 ssArgs <<
"(" << regname_or_literal(MEMB_abase, 0, 0) <<
")";
700 uint32_t offset = displacementWord + 8;
702 ssArgs.flags(std::ios::hex);
703 ssArgs << std::setfill(
'0') << std::setw(8) << offset;
709 ssArgs <<
"(" << regname_or_literal(MEMB_abase, 0, 0) <<
")";
710 ssArgs <<
"[" << regname_or_literal(MEMB_index, 0, 0) <<
"*" << scale <<
"]";
715 uint32_t offset = displacementWord;
717 ssArgs.flags(std::ios::hex);
718 ssArgs << std::setfill(
'0') << std::setw(8) << offset;
719 if (MEMB_mode == 0xd)
720 ssArgs <<
"(" << regname_or_literal(MEMB_abase, 0, 0) <<
")";
726 uint32_t offset = displacementWord;
728 ssArgs.flags(std::ios::hex);
729 ssArgs << std::setfill(
'0') << std::setw(8) << offset;
730 if (MEMB_mode == 0xf)
731 ssArgs <<
"(" << regname_or_literal(MEMB_abase, 0, 0) <<
")";
732 ssArgs <<
"[" << regname_or_literal(MEMB_index, 0, 0) <<
"*" << scale <<
"]";
736 ssArgs <<
"unimplemented MEMB mode!";
741 ssArgs.flags(std::ios::hex);
742 ssArgs << std::setfill(
'0') << std::setw(1) << MEMA_offset;
745 ssArgs <<
"(" << regname_or_literal(MEMA_abase, 0, 0) <<
")";
748 if (usesDst && !isStore) {
749 ssArgs <<
"," << regname_or_literal(MEMB_src_dst, 0, 0);
751 }
else if (iword == 0) {
754 ssOpcode <<
"unknown_0x";
755 ssOpcode.flags(std::ios::hex);
756 ssOpcode << std::setfill(
'0') << std::setw(2) << (int)opcode;
759 result.push_back(ssOpcode.str());
760 result.push_back(ssArgs.str());
761 string comments = ssComments.str();
762 if (comments.length() > 0)
763 result.push_back(comments);
771 if (attributeName ==
"stable")
774 if (attributeName ==
"description")
775 return "Intel i960 processor.";
787 cpu->m_pc =
ic->arg[0].u32;
788 cpu->DyntransPCtoPointers();
796 cpu->m_nextIC =
ic + 2;
810 uint32_t message =
REG32(
ic->arg[0]);
811 int type = (message >> 8) & 0xff;
816 UI* ui =
cpu->GetUI();
821 cpu->m_executedCycles --;
827 cpu->m_nextIC = &
cpu->m_abortIC;
829 UI* ui =
cpu->GetUI();
838 void I960_CPUComponent::Translate(uint32_t iword, uint32_t iword2,
struct DyntransIC*
ic)
842 unsigned int opcode = iword >> 24;
844 if (opcode >= 0x08 && opcode <= 0x1f) {
846 const int CTRL_disp = (iword >> 2) & 0x3fffff;
847 uint32_t disp = CTRL_disp << 2;
848 if (disp & 0x00800000)
853 if (opcode == 0x08) {
856 }
else if (opcode >= 0x58 && opcode <= 0x7f) {
858 const int REG_src_dst = (iword >> 19) & 0x1f;
859 const int REG_src2 = (iword >> 14) & 0x1f;
860 const int REG_m3 = (iword >> 13) & 0x1;
861 const int REG_m2 = (iword >> 12) & 0x1;
862 const int REG_m1 = (iword >> 11) & 0x1;
863 const int REG_opcode2 = (iword >> 7) & 0xf;
864 const int REG_s2 = (iword >> 6) & 0x1;
865 const int REG_s1 = (iword >> 5) & 0x1;
866 const int REG_src1 = (iword >> 0) & 0x1f;
868 int op3 = (opcode << 4) + REG_opcode2;
871 ic->
arg[0].
u32 = REG_src1;
874 ic->
arg[0].
p = &m_sfr[REG_src1];
876 ic->
arg[0].
p = &m_r[REG_src1];
880 ic->
arg[1].
u32 = REG_src2;
883 ic->
arg[1].
p = &m_sfr[REG_src1];
885 ic->
arg[1].
p = &m_r[REG_src2];
894 ic->
arg[2].
p = &m_r[REG_src_dst];
904 f_lit_lit_reg = instr_mov_lit_reg;
905 f_lit_reg_reg = instr_mov_lit_reg;
906 }
else if (op3 == 0x659) {
908 f_reg_reg_reg = instr_sysctl;
912 if (REG_m1 && REG_m2)
913 ic->
f = f_lit_lit_reg;
914 if (REG_m1 && !REG_m2)
915 ic->
f = f_lit_reg_reg;
916 if (!REG_m1 && REG_m2)
917 ic->
f = f_reg_lit_reg;
918 if (!REG_m1 && !REG_m2)
919 ic->
f = f_reg_reg_reg;
924 }
else if (opcode >= 0x80 && opcode <= 0xcf) {
926 const int MEMA_abase = (iword >> 14) & 0x1f;
927 const int MEMA_md = (iword >> 13) & 0x1;
928 const int MEMA_offset = (iword >> 0) & 0xfff;
929 const int MEMB_src_dst = (iword >> 19) & 0x1f;
930 const int MEMB_abase = (iword >> 14) & 0x1f;
931 const int MEMB_mode = (iword >> 10) & 0xf;
932 const int MEMB_scale = (iword >> 7) & 0x7;
933 const int MEMB_index = (iword >> 0) & 0x1f;
935 ic->
arg[2].
p = &m_r[MEMB_src_dst];
937 if (iword & 0x1000) {
942 ic->
f = instr_lda_displacement;
952 ic->
arg[0].
u32 = MEMA_offset;
953 ic->
f = instr_mov_lit_reg;
958 if (ic->
f == NULL && ui != NULL) {
960 ss.flags(std::ios::hex);
961 ss <<
"unimplemented opcode 0x" << opcode;
971 cpu->DyntransToBeTranslatedBegin(ic);
974 if (
cpu->DyntransReadInstruction(iword)) {
975 bool readCompleteInstruction =
true;
977 uint32_t opcode = iword >> 24;
978 if (opcode >= 0x80 && opcode <= 0xcf) {
980 int mode = (iword >> 10) & 0xf;
981 if (mode == 0x5 || mode >= 0xc)
982 readCompleteInstruction =
cpu->DyntransReadInstruction(iword2, 4);
983 if (!readCompleteInstruction) {
984 UI* ui =
cpu->GetUI();
989 if (readCompleteInstruction)
990 cpu->Translate(iword, iword2, ic);
993 cpu->DyntransToBeTranslatedDone(ic);
1000 #ifdef WITHUNITTESTS 1004 static void Test_I960_CPUComponent_Create()
1013 static void Test_I960_CPUComponent_Disassembly_Basic()
1018 vector<string> result;
1020 unsigned char instruction[
sizeof(uint32_t) * 2];
1023 instruction[0] = 0x00;
1024 instruction[1] = 0x30;
1025 instruction[2] = 0x68;
1026 instruction[3] = 0x8c;
1028 instruction[4] = 0x01;
1029 instruction[5] = 0x23;
1030 instruction[6] = 0x34;
1031 instruction[7] = 0x45;
1042 static GXemul SimpleMachine()
1053 static void Test_I960_CPUComponent_Execute_mov()
1055 GXemul gxemul = SimpleMachine();
1082 static void Test_I960_CPUComponent_Execute_b()
1084 GXemul gxemul = SimpleMachine();
1106 static void Test_I960_CPUComponent_Execute_lda_with_offset()
1108 GXemul gxemul = SimpleMachine();
1122 static void Test_I960_CPUComponent_Execute_lda_with_displacement()
1124 GXemul gxemul = SimpleMachine();
1142 UNITTEST(Test_I960_CPUComponent_Create);
1143 UNITTEST(Test_I960_CPUComponent_Disassembly_Basic);
1145 UNITTEST(Test_I960_CPUComponent_Execute_mov);
1146 UNITTEST(Test_I960_CPUComponent_Execute_b);
1147 UNITTEST(Test_I960_CPUComponent_Execute_lda_with_offset);
1148 UNITTEST(Test_I960_CPUComponent_Execute_lda_with_displacement);
void SetRunState(RunState newState)
Sets the RunState.
virtual CPUComponent * AsCPUComponent()
Returns the component's CPUComponent interface.
virtual void ShowDebugMessage(const string &msg)=0
Shows a debug message.
virtual int GetDyntransICshift() const
StateVariable * GetVariable(const string &name)
Gets a pointer to a state variable.
DYNTRANS_INSTR(I960_CPUComponent, b)
static refcount_ptr< Component > CreateComponent(const string &componentNameAndOptionalArgs, GXemul *gxemul=NULL)
Creates a component given a short component name.
void(* f)(CPUDyntransComponent *, DyntransIC *)
A Component representing an Intel i960 processor.
struct arm_instr_call * ic
virtual int FunctionTraceArgumentCount()
virtual bool PreRunCheckForComponent(GXemul *gxemul)
Checks the state of this component, before starting execution.
bool RunCommand(const string &command, bool *pSuccess=NULL)
Runs a command, given as a string.
virtual void ResetState()
Resets the state variables of this component.
bool AddVariable(const string &name, T *variablePointer)
Adds a state variable of type T to the Component.
UI * GetUI()
Gets an UI reference for outputting debug messages during runtime.
virtual bool WriteData(const uint8_t &data, Endianness endianness=BigEndian)=0
Writes 8-bit data to the currently selected address.
union DyntransIC::@0 arg[N_DYNTRANS_IC_ARGS]
A dyntrans instruction call.
I960_CPUComponent()
Constructs a I960_CPUComponent.
virtual uint64_t PCtoInstructionAddress(uint64_t pc)
Convert PC value to instuction address.
virtual int64_t FunctionTraceArgument(int n)
An interface for implementing components that read/write data via an address bus. ...
static string GetAttribute(const string &attributeName)
Creates a Component.
#define UNITTESTS(class)
Helper for unit test case execution.
CommandInterpreter & GetCommandInterpreter()
Gets a reference to the CommandInterpreter.
map< string, string > ComponentCreationSettings
static refcount_ptr< Component > Create(const ComponentCreateArgs &args)
Creates a I960_CPUComponent.
static string GetAttribute(const string &attributeName)
string LookupAddress(uint64_t vaddr, bool allowOffset) const
Looks up an address.
virtual bool PreRunCheckForComponent(GXemul *gxemul)
Checks the state of this component, before starting execution.
#define DYNTRANS_SYNCH_PC
SymbolRegistry & GetSymbolRegistry()
Gets a reference to the CPU's symbol registry.
virtual bool VirtualToPhysical(uint64_t vaddr, uint64_t &paddr, bool &writable)
Virtual to physical address translation (MMU).
virtual bool CheckVariableWrite(StateVariable &var, const string &oldValue)
Checks whether a write to a variable is OK.
A base-class for processors Component implementations that use dynamic translation.
uint64_t ToInteger() const
Returns the variable as an unsignedinteger value.
virtual size_t DisassembleInstruction(uint64_t vaddr, size_t maxlen, unsigned char *instruction, vector< string > &result)
Disassembles an instruction into readable strings.
StateVariables make up the persistent state of Component objects.
virtual bool CheckVariableWrite(StateVariable &var, const string &oldValue)
Checks whether a write to a variable is OK.
virtual void ShowRegisters(GXemul *gxemul, const vector< string > &arguments) const
A base-class for processors Component implementations.
virtual size_t DisassembleInstruction(uint64_t vaddr, size_t maxLen, unsigned char *instruction, vector< string > &result)=0
Disassembles an instruction into readable strings.
static void Assert(const string &strFailMessage, bool condition)
Asserts that a boolean condition is correct.
virtual void AddressSelect(uint64_t address)=0
Place an address on the bus.
virtual void ResetState()
Resets the state variables of this component.
bool SetVariableValue(const string &name, const string &expression)
Sets a variable to a new value.
refcount_ptr< Component > GetRootComponent()
Gets a pointer to the root configuration component.
virtual AddressDataBus * AsAddressDataBus()
Returns the component's AddressDataBus interface, if any.
#define DYNTRANS_INSTR_HEAD(class)
UI * GetUI()
Gets a pointer to the GXemul instance' active UI.
static bool GetCreationArgOverrides(ComponentCreationSettings &settings, const ComponentCreateArgs &createArgs)
Get override arguments for component creation.
Base class for a User Interface.
const refcount_ptr< Component > LookupPath(string path) const
Looks up a path from this Component, and returns a pointer to the found Component, if any.
void Execute(const int longestTotalRun=100000)
Run the emulation for "a while".
virtual void(*)(CPUDyntransComponent *, DyntransIC *) GetDyntransToBeTranslated()
struct reg_instruction reg_instructions[]
#define UNITTEST(functionname)
Helper for unit test case execution.
bool IsNULL() const
Checks whether or not an object is referenced by the reference counted pointer.
virtual bool FunctionTraceReturnImpl(int64_t &retval)