arm_emu.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034
  1. /*
  2. * Arm Processor Emulator
  3. *
  4. * Created on: Nov 12, 2012
  5. * Author: mdixon
  6. * Edited By: omufeed
  7. */
  8. // #include some headers you will be probably need
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <stdint.h>
  12. //Defines some types of our own. note: base these on platform independent types defined in <stdint.h>
  13. typedef uint64_t REGISTER; //registers are 32 bits
  14. typedef uint64_t WORD; //words are 32 bits
  15. typedef int32_t SWORD; //swords are 32 bits
  16. typedef uint8_t BYTE; //bytes are 8 bits
  17. typedef uint8_t BIT; //define bit data type
  18. //Define the shift amount for specific bits
  19. #define POS_CONDCODE (28)//Condition code
  20. #define POS_INSTYPE (26)//Instruction type
  21. #define POS_OPCODE (21)//Operation code
  22. #define POS_I (25)//Immediate bit
  23. #define POS_L (24)//Link bit
  24. #define POS_S (20)//Status bit
  25. #define POS_REGN (16)//regN
  26. #define POS_REGDEST (12)//regDest
  27. #define POS_ISHIFT (8)//Shift amount for immediate value
  28. #define POS_SHIFT (4)//Shift amount for operand register
  29. #define POS_IOPERAND (0)//Immediate value
  30. #define POS_OPERAND (0)//Operand register
  31. #define POS_N (31)//Negative bit
  32. #define POS_BOFFSET (0)//Offset for branch
  33. #define POS_P (24)//Pre/Post bit
  34. #define POS_U (23)//Up/Down bit
  35. #define POS_B (22)//Byte/Word bit
  36. #define POS_W (21)//Writeback into base register bit
  37. #define POS_LS (20)//Load/Store bit
  38. #define POS_SWICODE (0)//Software interrupt code
  39. //Define mask amount size
  40. #define MASK_1BIT (0x1)
  41. #define MASK_2BIT (0x3)
  42. #define MASK_3BIT (0x7)
  43. #define MASK_4BIT (0xf)
  44. #define MASK_5BIT (0x1f)
  45. #define MASK_6BIT (0x3f)
  46. #define MASK_7BIT (0x7f)
  47. #define MASK_8BIT (0xff)
  48. #define MASK_24BIT (0xffffff)
  49. //Define each condition code.
  50. #define CC_EQ (0x0)
  51. #define CC_NE (0x1)
  52. #define CC_CS (0x2)
  53. #define CC_CC (0x3)
  54. #define CC_MI (0x4)
  55. #define CC_PL (0x5)
  56. #define CC_VS (0x6)
  57. #define CC_VC (0x7)
  58. #define CC_HI (0x8)
  59. #define CC_LS (0x9)
  60. #define CC_GE (0xa)
  61. #define CC_LT (0xb)
  62. #define CC_GT (0xc)
  63. #define CC_LE (0xd)
  64. #define CC_AL (0xe)
  65. #define CC_NV (0xf)
  66. // Define each instruction type code.
  67. #define IT_DP (0x0)
  68. #define IT_DT (0x1)
  69. #define IT_BR (0x2)
  70. #define IT_SI (0x3)
  71. // Define each status flag
  72. #define STAT_N (1<<7)//Negative
  73. #define STAT_Z (1<<6)//Zero
  74. #define STAT_C (1<<5)//Carry
  75. #define STAT_V (1<<4)//Overflow
  76. #define STAT_I (1<<3)//Interrupt disabled
  77. #define STAT_F (1<<2)//Fast interrupt disabled
  78. #define STAT_P (3)//Processor operation mode, the last two bits. 00: User mode
  79. // Define each op code.
  80. #define OP_AND (0x0)
  81. #define OP_EOR (0x1)
  82. #define OP_SUB (0x2)
  83. #define OP_RSB (0x3)
  84. #define OP_ADD (0x4)
  85. #define OP_ADC (0x5)
  86. #define OP_SBC (0x6)
  87. #define OP_RSC (0x7)
  88. #define OP_TST (0x8)
  89. #define OP_TEQ (0x9)
  90. #define OP_CMP (0xa)
  91. #define OP_CMN (0xb)
  92. #define OP_ORR (0xc)
  93. #define OP_MOV (0xd)
  94. #define OP_BIC (0xe)
  95. #define OP_MVN (0xf)
  96. //custom SWI
  97. #define SYS_ADD10 (0x01)//Add 10 to R0
  98. #define SYS_POS_ADD10 (0x01)//Add 10 to R0
  99. //Define instruction handling result type, include further error types
  100. #define INST_VALID (1<<1)
  101. #define INST_CONDITIONNOTMET (1<<2)
  102. #define INST_INVALID (1<<3)
  103. #define INST_MULTIPLYBYZERO (1<<4)
  104. #define INST_RESTRICTEDMEMORYBLOCK (1<<5)
  105. int maxMemorySize = 4096;//Temporarily set the memory size to 140 to better monitor the data in memory during the output, increase this value as required.
  106. int userMemoryIndex = 120;//from 120 to maxMemorySize can be used by user to load/store data
  107. int stkMemoryIndex = 100;//next 20 are reserved for stack
  108. int instMemoryIndex = 52;//next 48 are reserved for user instructions. No access for user load/store data
  109. int swiMemoryIndex = 12;//next 40 are reserved for interrupt instructions. No access for user load/store data
  110. int swibMemoryIndex = 0;//First 12 rows are the interrupts branch instruction. No access for user load/store data
  111. //storing registers within array makes execution code simpler
  112. REGISTER registers[16];
  113. //4 kilobytes of RAM in this example (since 1 word = 4 bytes)
  114. WORD* memory = (WORD)0;
  115. //the variable to fetch the instruction into
  116. WORD inst;
  117. BYTE regStatus = 0;//status register
  118. int totalCycleCount = 0, instCycleCount = 0;
  119. BYTE instResult = INST_VALID;//Instruction result handler
  120. //Variables for data processing instructions
  121. BIT iBit = 0, sBit = 0, lBit = 0, pBit = 0, uBit = 0, bBit = 0, wBit = 0, lsBit = 0;
  122. BYTE opCode, regN, regDest, shiftAmount;
  123. WORD operand, offset, swiCode;
  124. //Turn on/off the debug mode; prints assisting data about the operation steps
  125. int debugEnabled = 1;
  126. //Turn on/off the instruction log; prints the type and input of the instruction
  127. int instructionLogEnabled = 1;
  128. //Listens to the keyboard input and is turned on if space is clicked. If it is on, an interrupt is fired
  129. int feedback = 0;
  130. //Get the negative value, use two's complement for negation
  131. WORD getNegative(WORD value){
  132. return ~value + 1;
  133. }
  134. //Check if a specific value is negative, use two's complement for negation
  135. int isNegative(WORD value){
  136. return (((value >> POS_N) & MASK_1BIT));
  137. }
  138. //Check if a specific value is positive
  139. int isPositive(WORD value){
  140. return !(((value >> POS_N) & MASK_1BIT));
  141. }
  142. //Check if a specific 24 bit value is negative, use two's complement for negation. 24bit negative value is used for offset
  143. int isNegative24bit(WORD value){
  144. return (((value >> (23)) & MASK_1BIT));
  145. }
  146. //Get the negative value, use two's complement for negation
  147. WORD getNegative24bit(WORD value){
  148. return (~value & MASK_24BIT) + 1;
  149. }
  150. //The carry flag is set if the addition of two numbers causes a carry out of the most significant (leftmost) bits added.
  151. int isCarryAdd(WORD op1Value, WORD op2Value, WORD result)
  152. {
  153. return ((isNegative(op1Value) && isNegative(op2Value)) || (isNegative(op1Value) && isPositive(result)) || (isNegative(op2Value) && isPositive(result)));
  154. }
  155. //The carry (borrow) flag is also set if the subtraction of two numbers requires a borrow into the most significant (leftmost) bits subtracted.
  156. int isCarrySub(WORD op1Value, WORD op2Value, WORD result){
  157. return ((isNegative(op1Value) && isPositive(op2Value)) || (isNegative(op1Value) && isPositive(result)) || (isPositive(op2Value) && isPositive(result)));
  158. }
  159. //If the sum of two numbers with the sign bits off yields a result number with the sign bit on, the "overflow" flag is turned on.
  160. int isOverflowAdd(WORD op1Value, WORD op2Value, WORD result)
  161. {
  162. return ((isNegative(op1Value) && isNegative(op2Value) && isPositive(result)) || (isPositive(op1Value) && isPositive(op2Value) && isNegative(result)));
  163. }
  164. //If the sum of two numbers with the sign bits on yields a result number with the sign bit off, the "overflow" flag is turned on.
  165. int isOverflowSub(WORD op1Value, WORD op2Value, WORD result){
  166. return ((isNegative(op1Value) && isPositive(op2Value) && isPositive(result)) || (isPositive(op1Value) && isNegative(op2Value) && isNegative(result)));
  167. }
  168. //Provide some support functions to test condition of a specified SR flag
  169. int isSet(int flag)
  170. {
  171. return (regStatus & flag) == flag;
  172. }
  173. int isClear(int flag)
  174. {
  175. return ((~regStatus) & flag) == flag;
  176. }
  177. void setFlag(int flag)
  178. {
  179. regStatus = regStatus | flag;
  180. }
  181. void clearFlag(int flag)
  182. {
  183. regStatus = regStatus & (~flag);
  184. }
  185. //set the SR flags by examining the result. The previous value of flags get initiated as well.
  186. void setStatusReg(int isZ, int isN, int isC, int isV, int isI, int isF, int isP){
  187. //Set or clear the Zero, Negative, Carry, Overflow, Interrupt disabled and Fast interrupt disabled flags
  188. isN ? setFlag(STAT_N) : clearFlag(STAT_N);
  189. isZ ? setFlag(STAT_Z) : clearFlag(STAT_Z);
  190. isC ? setFlag(STAT_C) : clearFlag(STAT_C);
  191. isV ? setFlag(STAT_V) : clearFlag(STAT_V);
  192. isI ? setFlag(STAT_I) : clearFlag(STAT_I);
  193. isF ? setFlag(STAT_F) : clearFlag(STAT_F);
  194. //Check the processor operation mode and set the flags
  195. }
  196. // Write a function for each supported operation
  197. void doAnd(int regNumber, WORD op1Value, WORD op2Value, int setSR)
  198. {
  199. if (instructionLogEnabled) printf("Operation: AND %d %d\n", op1Value, op2Value);
  200. WORD result = op1Value & op2Value;
  201. registers[regNumber] = result;
  202. if (setSR) setStatusReg(result == 0, isNegative(result), 0, 0, 0, 0, 0);
  203. }
  204. void doOrr(int regNumber, WORD op1Value, WORD op2Value, int setSR)
  205. {
  206. if (instructionLogEnabled) printf("Operation: ORR %d %d\n", op1Value, op2Value);
  207. WORD result = op1Value | op2Value;
  208. registers[regNumber] = result;
  209. if (setSR) setStatusReg(result == 0, isNegative(result), 0, 0, 0, 0, 0);
  210. }
  211. void doEor(int regNumber, WORD op1Value, WORD op2Value, int setSR)
  212. {
  213. if (instructionLogEnabled) printf("Operation: EOR %d %d\n", op1Value, op2Value);
  214. WORD result = op1Value ^ op2Value;
  215. registers[regNumber] = result;
  216. if (setSR) setStatusReg(result == 0, isNegative(result), 0, 0, 0, 0, 0);
  217. }
  218. /*doAdd
  219. * Adds op1Value to op2Value and stores in the specified register
  220. *
  221. * enter: regNumber - the number of the destination register (0-15)
  222. * op1Value - the first value to be added
  223. * op2Value - the second value to be added
  224. * setSR - flag, if non-zero then the status register should be updated, else it shouldn't
  225. */
  226. void doAdd(int regNumber, WORD op1Value, WORD op2Value, int setSR)
  227. {
  228. if (instructionLogEnabled) printf("Operation: ADD %d %d\n", op1Value, op2Value);
  229. WORD result = op1Value + op2Value;
  230. registers[regNumber] = result;
  231. if (setSR) setStatusReg(result == 0, isNegative(result), isCarryAdd(op1Value, op2Value, result), isOverflowAdd(op1Value, op2Value, result), 0, 0, 0);
  232. }
  233. void doAdc(int regNumber, WORD op1Value, WORD op2Value, int setSR)
  234. {
  235. if (instructionLogEnabled) printf("Operation: ADD %d %d\n", op1Value, op2Value);
  236. WORD result = op1Value + op2Value + isSet(STAT_C);
  237. registers[regNumber] = result;
  238. if (setSR) setStatusReg(result == 0, isNegative(result), isCarryAdd(op1Value, op2Value, result), isOverflowAdd(op1Value, op2Value, result), 0, 0, 0);
  239. }
  240. void doSub(int regNumber, WORD op1Value, WORD op2Value, int setSR)
  241. {
  242. if (instructionLogEnabled) printf("Operation: SUB %d %d\n", op1Value, op2Value);
  243. WORD result = op1Value - op2Value;
  244. registers[regNumber] = result;
  245. if (setSR) setStatusReg(result == 0, isNegative(result), isCarrySub(op1Value, op2Value, result), isOverflowSub(op1Value, op2Value, result), 0, 0, 0);
  246. }
  247. void doSbc(int regNumber, WORD op1Value, WORD op2Value, int setSR)
  248. {
  249. if (instructionLogEnabled) printf("Operation: SUB %d %d\n", op1Value, op2Value);
  250. WORD result = op1Value - op2Value - isClear(STAT_C);
  251. registers[regNumber] = result;
  252. if (setSR) setStatusReg(result == 0, isNegative(result), isCarrySub(op1Value, op2Value, result), isOverflowSub(op1Value, op2Value, result), 0, 0, 0);
  253. }
  254. void doRsb(int regNumber, WORD op1Value, WORD op2Value, int setSR)
  255. {
  256. if (instructionLogEnabled) printf("Operation: RSB %d %d\n", op1Value, op2Value);
  257. WORD result = op2Value - op1Value;
  258. registers[regNumber] = result;
  259. if (setSR) setStatusReg(result == 0, isNegative(result), isCarrySub(op2Value, op1Value, result), isOverflowSub(op2Value, op1Value, result), 0, 0, 0);
  260. }
  261. void doRsc(int regNumber, WORD op1Value, WORD op2Value, int setSR)
  262. {
  263. if (instructionLogEnabled) printf("Operation: RSB %d %d\n", op1Value, op2Value);
  264. WORD result = op2Value - op1Value - isClear(STAT_C);
  265. registers[regNumber] = result;
  266. if (setSR) setStatusReg(result == 0, isNegative(result), isCarrySub(op2Value, op1Value, result), isOverflowSub(op2Value, op1Value, result), 0, 0, 0);
  267. }
  268. void doMov(int regNumber, WORD opValue, int setSR)
  269. {
  270. if (instructionLogEnabled) printf("Operation: MOV R%d %d\n", regNumber, opValue);
  271. registers[regNumber] = opValue;
  272. if (setSR) setStatusReg(opValue == 0, isNegative(opValue), 0, 0, 0, 0, 0);
  273. }
  274. void doMvn(int regNumber, WORD opValue, int setSR)
  275. {
  276. if (instructionLogEnabled) printf("Operation: MVN R%d %d\n", regNumber, opValue);
  277. registers[regNumber] = ~opValue;
  278. if (setSR) setStatusReg(~opValue == 0, isNegative(~opValue), 0, 0, 0, 0, 0);
  279. }
  280. //The processor always assumes the status flag is set, either it is actually set or not
  281. void doCmp(WORD op1Value, WORD op2Value)
  282. {
  283. if (instructionLogEnabled) printf("Operation: CMP %d %d\n", op1Value, op2Value);
  284. WORD result = op1Value - op2Value;
  285. setStatusReg(result == 0, isNegative(result), isCarrySub(op1Value, op2Value, result), isOverflowSub(op1Value, op2Value, result), 0, 0, 0);
  286. }
  287. //The processor always assumes the status flag is set, either it is actually set or not
  288. void doCmn(WORD op1Value, WORD op2Value)
  289. {
  290. if (instructionLogEnabled) printf("Operation: CMN %d %d\n", op1Value, op2Value);
  291. WORD result = op1Value + op2Value;
  292. setStatusReg(result == 0, isNegative(result), isCarryAdd(op1Value, op2Value, result), isOverflowAdd(op1Value, op2Value, result), 0, 0, 0);
  293. }
  294. //The processor always assumes the status flag is set, either it is actually set or not
  295. void doTst(WORD op1Value, WORD op2Value)
  296. {
  297. if (instructionLogEnabled) printf("Operation: TST %d %d\n", op1Value, op2Value);
  298. setStatusReg((op1Value & op2Value) == 0, isNegative(op1Value & op2Value), 0, 0, 0, 0, 0);
  299. }
  300. //The processor always assumes the status flag is set, either it is actually set or not
  301. void doTeq(WORD op1Value, WORD op2Value)
  302. {
  303. if (instructionLogEnabled) printf("Operation: TEQ %d %d\n", op1Value, op2Value);
  304. setStatusReg((op1Value ^ op2Value) == 0, isNegative(op1Value ^ op2Value), 0, 0, 0, 0, 0);
  305. }
  306. void doBic(int regNumber, WORD op1Value, WORD op2Value, int setSR)
  307. {
  308. if (instructionLogEnabled) printf("Operation: BIC %d %d\n", op1Value, op2Value);
  309. WORD result = op1Value & ~op2Value;
  310. registers[regNumber] = result;
  311. if (setSR) setStatusReg(result == 0, isNegative(result), 0, 0, 0, 0, 0);
  312. }
  313. //Store a value of register regNumber into stack and increase the stack pointer
  314. void stkPush(int regNumber){
  315. memory[registers[13]++] = registers[regNumber];
  316. }
  317. //Load a latest from stack into the register regNumber and decrease the stack pointer
  318. void stkPop(int regNumber){
  319. registers[regNumber] = memory[registers[13]--];
  320. }
  321. //Decide whether the instruction should be executed by examining the appropriate status register flags, depending on condition code.
  322. int getConditionCode(WORD inst){
  323. int exec = 0;
  324. int conditionCode;
  325. // Start by extracting the condition code
  326. conditionCode = inst >> POS_CONDCODE; // get the condition flags (top 4 bits of the instruction).
  327. switch ( conditionCode ) {
  328. case CC_EQ:
  329. // check if zero flag is set
  330. exec = isSet(STAT_Z);
  331. break;
  332. case CC_NE:
  333. // check if zero flag is clear
  334. exec = isClear(STAT_Z);
  335. break;
  336. case CC_CS:
  337. exec = isSet(STAT_C);
  338. break;
  339. case CC_CC:
  340. exec = isClear(STAT_C);
  341. break;
  342. case CC_MI:
  343. exec = isSet(STAT_N);
  344. break;
  345. case CC_PL:
  346. exec = isClear(STAT_N);
  347. break;
  348. case CC_VS:
  349. exec = isSet(STAT_V);
  350. break;
  351. case CC_VC:
  352. exec = isClear(STAT_V);
  353. break;
  354. case CC_HI:
  355. //If C is set and Z is clear, means > for unsigned
  356. exec = isSet(STAT_C) && isClear(STAT_Z);
  357. break;
  358. case CC_LS:
  359. //<= unsigned
  360. exec = isClear(STAT_C) && isSet(STAT_Z);
  361. break;
  362. case CC_GE:
  363. //>= signed
  364. exec = (isClear(STAT_N) && isClear(STAT_V)) || (isSet(STAT_N) && isSet(STAT_V));
  365. break;
  366. case CC_LT:
  367. // < signed
  368. exec = ( isSet( STAT_N ) && isClear( STAT_V ) ) || ( isClear(STAT_N) && isSet(STAT_V) ) ;
  369. break;
  370. case CC_GT:
  371. // > signed
  372. exec = isClear(STAT_Z) && ((isClear(STAT_N) && isClear(STAT_V)) || (isSet(STAT_N) && isSet(STAT_V)));
  373. break;
  374. case CC_LE:
  375. // <= signed
  376. exec = isSet(STAT_Z) || ( isSet( STAT_N ) && isClear( STAT_V ) ) || ( isClear(STAT_N) && isSet(STAT_V) ) ;
  377. break;
  378. case CC_AL:
  379. exec = 1;
  380. break;
  381. case CC_NV:
  382. exec = 0;
  383. break;
  384. }
  385. return exec;
  386. }
  387. //Do the data processing type operations
  388. void doDataProcessing(WORD inst){
  389. iBit = (inst >> POS_I) & MASK_1BIT;//Get Immediate bit
  390. opCode = (inst >> POS_OPCODE) & MASK_4BIT;//Get Opcode, 4 bits
  391. sBit = (inst >> POS_S) & MASK_1BIT;//Get Status bit
  392. regN = (inst >> POS_REGN) & MASK_4BIT;//Get RegN, 4 bits
  393. regDest = (inst >> POS_REGDEST) & MASK_4BIT;//Get RegDest, 4 bits
  394. //Get the operand depending to the Immediate code
  395. if(iBit){
  396. shiftAmount = (inst >> POS_ISHIFT) & MASK_4BIT;//Immediate shift is 4 bits
  397. operand = (inst >> POS_IOPERAND) & MASK_8BIT;//Immediate value is 8 bits
  398. }
  399. else{
  400. shiftAmount = (inst >> POS_SHIFT) & MASK_8BIT;//Non-immediate shift is 8 bits
  401. operand = registers[(inst >> POS_OPERAND) & MASK_4BIT];//Non-immediate register number is 4 bits
  402. }
  403. //Apply the shift amount to the operand
  404. operand = operand << shiftAmount;
  405. //Print the decoded instruction if debug is enabled
  406. if (debugEnabled){
  407. printf("Immediate bit: %01X\n", iBit);
  408. printf("Op code: %01X\n", opCode);
  409. printf("Status bit: %01X\n", sBit);
  410. printf("RegN code: %01X\n", regN);
  411. printf("RegDest code: %01X\n", regDest);
  412. printf("operand : %d\n", operand);
  413. }
  414. switch(opCode)
  415. {
  416. case OP_AND:
  417. doAnd(regDest, registers[regN], operand, sBit);
  418. break;
  419. case OP_EOR:
  420. doEor(regDest, registers[regN], operand, sBit);
  421. break;
  422. case OP_SUB:
  423. doSub(regDest, registers[regN], operand, sBit);
  424. break;
  425. case OP_RSB:
  426. doRsb(regDest, registers[regN], operand, sBit);
  427. break;
  428. case OP_ADD:
  429. doAdd(regDest, registers[regN], operand, sBit);
  430. break;
  431. case OP_ADC:
  432. doAdc(regDest, registers[regN], operand, sBit);
  433. break;
  434. case OP_SBC:
  435. doSbc(regDest, registers[regN], operand, sBit);
  436. break;
  437. case OP_RSC:
  438. doRsc(regDest, registers[regN], operand, sBit);
  439. break;
  440. case OP_TST:
  441. doTst(registers[regN], operand);
  442. break;
  443. case OP_TEQ:
  444. doTeq(registers[regN], operand);
  445. break;
  446. case OP_CMP:
  447. doCmp(registers[regN], operand);
  448. break;
  449. case OP_CMN:
  450. doCmn(registers[regN], operand);
  451. break;
  452. case OP_ORR:
  453. doOrr(regDest, registers[regN], operand, sBit);
  454. break;
  455. case OP_MOV:
  456. doMov(regDest, operand, sBit);
  457. break;
  458. case OP_BIC:
  459. doBic(regDest, registers[regN], operand, sBit);
  460. break;
  461. case OP_MVN:
  462. doMvn(regDest, operand, sBit);
  463. break;
  464. default:
  465. instResult = INST_INVALID;
  466. break;
  467. }
  468. //Update the cycle count. If regDest is PC the +2, otherwise 1 cycle.
  469. instCycleCount = (regDest == 15) ? 3 : 1;
  470. }
  471. //Do the branch type operations
  472. void doBranch(WORD inst){
  473. lBit = (inst >> POS_L) & MASK_1BIT;//Get Link bit
  474. offset = (inst >> POS_BOFFSET) & MASK_24BIT;//Get the offset, 24 bits
  475. if (instructionLogEnabled) printf("Operation: B %d\n", offset);
  476. if(lBit){
  477. //Check if there is already a link value in R14. Push to the stack if there is before overwriting it
  478. if (registers[14] > 0) stkPush(14);
  479. //Store the PC in link(R14)
  480. registers[14] = registers[15];
  481. }
  482. //Check if the 24bit offset value is negative? if yes then subtract the positive value of the offset, otherwise add the offset value
  483. if(isNegative24bit(offset)){
  484. registers[15] -= getNegative24bit(offset) / 4;
  485. }else{
  486. registers[15] += offset / 4;
  487. }
  488. registers[15] += 4;//Add 4 to the PC, because of the pipeline
  489. //Update the cycle count
  490. instCycleCount = 3;
  491. }
  492. //Do the data transfer operation
  493. void doDataTransfer(WORD inst){
  494. iBit = (inst >> POS_I) & MASK_1BIT;//Get Immediate bit
  495. pBit = (inst >> POS_P) & MASK_1BIT;//Get Pre/Post bit
  496. uBit = (inst >> POS_U) & MASK_1BIT;//Get Up/Down bit
  497. bBit = (inst >> POS_B) & MASK_1BIT;//Get Byte/Word bit
  498. wBit = (inst >> POS_W) & MASK_1BIT;//Get Writeback to base register bit
  499. lsBit = (inst >> POS_LS) & MASK_1BIT;//Get Load/Store bit
  500. regN = (inst >> POS_REGN) & MASK_4BIT;//Get RegN, 4 bits
  501. regDest = (inst >> POS_REGDEST) & MASK_4BIT;//Get RegDest, 4 bits
  502. //Get the operand depending to the Immediate code
  503. if(iBit){
  504. shiftAmount = (inst >> POS_ISHIFT) & MASK_4BIT;//Immediate shift is 4 bits
  505. offset = (inst >> POS_IOPERAND) & MASK_8BIT;//Immediate value is 8 bits
  506. if (debugEnabled) printf("Shift amount code: %01X\n", shiftAmount);
  507. }
  508. else{
  509. shiftAmount = (inst >> POS_SHIFT) & MASK_8BIT;//Non-immediate shift is 8 bits
  510. offset = registers[(inst >> POS_OPERAND) & MASK_4BIT];//Non-immediate register number is 4 bits
  511. if (debugEnabled) printf("Shift amount code: %02X\n", shiftAmount);
  512. }
  513. if (instructionLogEnabled){
  514. printf("Operation: ");
  515. printf(lsBit ? "LDR" : "STR");
  516. printf(" R%d R%d, %d\n", regDest, regN, offset);
  517. }
  518. //Print the decoded instruction if debug is enabled
  519. if (debugEnabled){
  520. printf("Immediate bit: %01X\n", iBit);
  521. printf("Pre/Post bit: %01X\n", pBit);
  522. printf("Up/Down bit: %01X\n", uBit);
  523. printf("Byte/Word bit: %01X\n", bBit);
  524. printf("Writeback to base register bit: %01X\n", wBit);
  525. printf("Load/Store bit: %01X\n", lsBit);
  526. printf("RegN code: %01X\n", regN);
  527. printf("RegDest code: %01X\n", regDest);
  528. printf("offset : %d\n", offset);
  529. }
  530. //Set the initial memory index
  531. int memoryIndex = registers[regN];
  532. //If the pre bit is set, add/subtract offset to the base register before the transfer
  533. if(pBit) memoryIndex = (uBit) ? memoryIndex + offset : memoryIndex - offset;
  534. //Check if the instruction is trying to access the restricted memory blocks
  535. if ((memoryIndex >= userMemoryIndex) && (memoryIndex <= maxMemorySize)){
  536. //If load/store bit is set load, if not store
  537. if(lsBit) registers[regDest] = (wBit) ? memory[memoryIndex] : memory[memoryIndex] & MASK_4BIT;//If the word/byte bit is set, load the least significant byte from the noted memory address
  538. else memory[memoryIndex] = (wBit) ? registers[regDest] : registers[regDest] & MASK_4BIT;//If the word/byte bit is set, store the least significant byte from regDest
  539. //If the pre bit is not set, add/subtract offset to the base register after the transfer
  540. if(!pBit) memoryIndex = (uBit) ? memoryIndex + offset : memoryIndex - offset;
  541. //Set the base register value with the new index if the writeback is set
  542. if(wBit) registers[regN] = memoryIndex;
  543. //Update the cycle count. If it is LDR 3 cycles and +2 if regDest is PC. If it is STR then 2 cycles.
  544. instCycleCount = (lsBit) ? (regDest == 15) ? 5 : 3 : 2;
  545. }
  546. else{
  547. instResult = INST_RESTRICTEDMEMORYBLOCK;
  548. }
  549. }
  550. //Handle the software interrupt
  551. void doSoftwareInterrupt(WORD inst){
  552. swiCode = (inst >> POS_SWICODE) & MASK_24BIT;//Interrupt code value is 24 bits
  553. if (instructionLogEnabled) printf("Interrup: SWI %d\n", swiCode);
  554. registers[14] = registers[15];//Backup the PC from return from interrupt
  555. registers[15] = swiCode + 4;//Jump to the branch address in vector table +4 for pipeline
  556. //Update the cycle count
  557. instCycleCount = 5;
  558. }
  559. // The main work will happen inside this function. It should decode then execute the passed instruction.
  560. void decodeAndExecute(WORD inst){
  561. int insTypeCode;
  562. int exec;
  563. if (debugEnabled) printf("Decoding: %04X\n",inst); // output the instruction being decoded
  564. exec = getConditionCode(inst);
  565. // only decode and execute the instruction if required to do so, i.e. condition satisfied.
  566. if ( exec ) {
  567. // next stage is to decode which type of instruction we have, so want to look at bits 27, 26
  568. insTypeCode = (inst >> POS_INSTYPE) & MASK_2BIT;
  569. if (debugEnabled) printf("Ins type code: %01X\n", insTypeCode);
  570. // once we know the instruction we can execute it!
  571. switch(insTypeCode){
  572. case IT_DP:
  573. doDataProcessing(inst);
  574. break;
  575. case IT_DT:
  576. doDataTransfer(inst);
  577. break;
  578. case IT_BR:
  579. doBranch(inst);
  580. break;
  581. case IT_SI:
  582. doSoftwareInterrupt(inst);
  583. break;
  584. default:
  585. instResult = INST_INVALID;
  586. break;
  587. }
  588. }
  589. else{
  590. instResult = INST_CONDITIONNOTMET;
  591. }
  592. }
  593. //Add delay and get feedback either to interrupt, exit or continue to next instruction
  594. void getFeedback(){
  595. printf("Please enter (i)Interrupt, (x)Exit, (g)Continue: ");
  596. feedback = getchar();
  597. //Another getchar() to absorb the enter pressed after the value entered
  598. getchar();
  599. //if entered char = i(105) then set interrupt
  600. if ((feedback == 105)){
  601. //If hardware interrupt has happened, then execute the sample interrupt
  602. doSoftwareInterrupt(0xEF000001);
  603. }else if(feedback == 120){//if feedback is x(120)
  604. memory[(registers[15] - 4)] = 0;//Set next instruction as 0, so the program will eixt
  605. }
  606. }
  607. // Print the result of the registers, memory and the other required optputs
  608. void printOutput(){
  609. if (instResult == INST_VALID){
  610. //Print register values
  611. printf("Registers\n");
  612. int i;
  613. for(i = 0; i<16; i++){
  614. printf("-R%d: %d ", i, registers[i]);
  615. }
  616. printf("\n");
  617. //Print only the user accessible memory values
  618. printf("Memory\n");
  619. for(i = userMemoryIndex; i < maxMemorySize; i++){
  620. printf("-M[%d]: %d ", i, memory[i]);
  621. }
  622. printf("\n");
  623. //Print the stack
  624. printf("Stack\n");
  625. for(i = stkMemoryIndex; i < userMemoryIndex; i++){
  626. printf("-S[%d]: %d ", i, memory[i]);
  627. }
  628. printf("\n");
  629. if (debugEnabled) printf("-Status Register: %X ", regStatus);//Print status register
  630. //Print status flags
  631. printf("Flags\n");
  632. printf("-Negative: %d ", isSet(STAT_N));
  633. printf("-Zero: %d ", isSet(STAT_Z));
  634. printf("-Carry: %d ", isSet(STAT_C));
  635. printf("-Overflow: %d ", isSet(STAT_V));
  636. printf("-Interrupt disabled: %d ", isSet(STAT_I));
  637. printf("-Fast interrupt disabled: %d ", isSet(STAT_F));
  638. printf("-Processor operation mode: %d ", isSet(STAT_P));
  639. printf("\n");
  640. } else{
  641. switch(instResult){
  642. case INST_CONDITIONNOTMET:
  643. printf("The condition is not met.\n");
  644. break;
  645. case INST_INVALID:
  646. printf("The instruction is invalid.\n");
  647. break;
  648. case INST_MULTIPLYBYZERO:
  649. printf("The instruction causes multiply by zero.\n");
  650. break;
  651. case INST_RESTRICTEDMEMORYBLOCK:
  652. printf("Restricted memory block. End users have access to memory indexes greater then %d\n", (userMemoryIndex - 1) );
  653. break;
  654. default:
  655. printf("Unexpected error happened.\n");
  656. break;
  657. }
  658. }
  659. }
  660. int arm_emulate(uint64_t* binary) {
  661. int isFinished = 0;
  662. uint64_t* memoryIndex = (WORD)binary;//Initialise the memory index for the instructions block
  663. int instCount = 0;
  664. int i = 0;
  665. for(i = 0; i < 16; i++) {
  666. registers[i] = 0;
  667. }
  668. registers[15] = binary+4;
  669. printf("r15: %p\n",registers[15]);
  670. printf("r15-4: %p\n",(WORD*)registers[15] - 4);
  671. while(!isFinished)
  672. {
  673. //After each instruction is completed, get user feedback
  674. getFeedback();
  675. // fetch the next instruction. Subtract 4 from the PC, because of the pipeline PC points to 4 instructions forward
  676. inst = *((WORD*)registers[15] - 4) & 0xffffffff;
  677. //increment the PC(register[15]) to point at the next instruction
  678. registers[15]++;
  679. //Initialise the instruction result values
  680. instResult = INST_VALID;
  681. //Initialise the instruction cycle count to 1, because it will take at least 1 cycle even if the condition is not met
  682. instCycleCount = 1;
  683. if ( inst != 0 ) {
  684. printf("---------- Instruction %d ----------\n", instCount);
  685. decodeAndExecute(inst);
  686. printOutput();
  687. //Update total cycle count
  688. totalCycleCount += instCycleCount;
  689. printf("---------- %d Cycles, end of instruction %d----------\n", instCycleCount, instCount);
  690. //Increase the amount of instructions executed
  691. instCount++;
  692. }
  693. else {
  694. // found an instruction with the value 0
  695. // finish once a 0 hit. Not correct behaviour but good for testing
  696. isFinished = 1;
  697. //Total instruction count doesn't include the finish instruction
  698. printf("========== %d Total cycles for %d instructions ==========\n", totalCycleCount, instCount);
  699. printf("Press enter to exit...\n");
  700. getchar();
  701. }
  702. }
  703. // all ok
  704. return 0;
  705. }
  706. int arm_emu_main(void)
  707. {
  708. int isFinished = 0;
  709. int memoryIndex = instMemoryIndex;//Initialise the memory index for the instructions block
  710. int instCount = 0;
  711. //Technically the register values would be 0 anyway, yet this is a double check to make sure they are initialised
  712. int i = 0;
  713. for(i = 0; i < 16; i++){
  714. registers[i] = 0;
  715. }
  716. //initialise the stack pointer to the initial index of stack memory
  717. registers[13] = stkMemoryIndex;
  718. //initialise the PC to start from the instruction memory index. Add 4 for pipeline
  719. registers[15] = instMemoryIndex + 4;
  720. /*Interrupt branch instructions*/
  721. //B #28 1110 1010 0000 0000 0000 0000 0001 1100 //branch to #13: Add 10 to R0. Jump to 11-4 next memory location, since PC is already showing the next instruction and another 4 because of pipeline
  722. memory[swibMemoryIndex + SYS_ADD10] = 0xEA00001C;
  723. //End Interrupt branch instructions
  724. /*Interrupt instructions*/
  725. //ADD R0,R0,#10 1110 0010 1000 0000 0000 0000 0000 1010 //Add 10 to R0
  726. memory[swiMemoryIndex + SYS_POS_ADD10] = 0xE280000A;
  727. //MOV R15,R14 1110 0001 1010 0000 1111 0000 0000 1110 //branch back to where interrupt was called
  728. memory[swiMemoryIndex + SYS_POS_ADD10 + 1] = 0xE1A0F00E;
  729. //End Interrupt instructions
  730. //for testing purposes put some data into the memory. This data represents the instructions to be executed.
  731. /*Math instructions
  732. //MOV r0,#9 1110 0011 1010 0000 0000 0000 0000 1001
  733. memory[memoryIndex++] = 0xE3A00009;
  734. //MOV r1,#8 1110 0011 1010 0000 0001 0000 0000 1000
  735. memory[memoryIndex++] = 0xE3A01008;
  736. //ADD r2,r0,r1 1110 0000 1000 0000 0010 0000 0000 0001
  737. memory[memoryIndex++] = 0xE0802001;
  738. //ADD r3,r0,#5 1110 0010 1000 0000 0011 0000 0000 0101
  739. memory[memoryIndex++] = 0xE2803005;
  740. //SUB r4,r2,#5 1110 0010 0100 0010 0100 0000 0000 0101
  741. memory[memoryIndex++] = 0xE2424005;
  742. //RSBS r5,r0,#5 1110 0010 0111 0000 0101 0000 0000 0101
  743. memory[memoryIndex++] = 0xE2705005;
  744. //ADDS r6,r0,#205 1110 0010 1001 0000 0110 0000 1100 1101
  745. memory[memoryIndex++] = 0xE29060CD;
  746. //BICS r7,r0,#1 1110 0011 1101 0000 0111 0000 0000 0001
  747. memory[memoryIndex++] = 0xE3D07001;*/
  748. //End Math instructions
  749. /*Logic instructions
  750. //MOVS r0,#9 1110 0011 1011 0000 0000 0000 0000 1001
  751. memory[memoryIndex++] = 0xE3B00009;
  752. //MOVS r1,#12 1110 0011 1011 0000 0001 0000 0000 1100
  753. memory[memoryIndex++] = 0xE3B0100C;
  754. //MVNS r5,#2 1110 0011 1111 0000 0101 0000 0000 0010
  755. //memory[memoryIndex++] = 0xE3F05002;
  756. //AND r2,r0,r1 1110 0000 0000 0000 0010 0000 0000 0001
  757. //memory[memoryIndex++] = 0xE0002001;
  758. //ORR r3,r0,r1 1110 0001 1000 0000 0011 0000 0000 0001
  759. //memory[memoryIndex++] = 0xE1803001;
  760. //EOR r4,r0,r1 1110 0000 0010 0000 0100 0000 0000 0001
  761. //memory[memoryIndex++] = 0xE0204001;
  762. //CMP r2,#9 1110 0011 0101 0010 0000 0000 0000 1001
  763. //memory[memoryIndex++] = 0xE3520009;
  764. //CMN r5,#1 1110 0011 0111 0101 0000 0000 0000 0001
  765. //memory[memoryIndex++] = 0xE3750001;
  766. //TST r1,#0 1110 0011 0001 0001 0000 0000 0000 0000
  767. memory[memoryIndex++] = 0xE3110000;
  768. //TEQ r1,#12 1110 0011 0011 0001 0000 0000 0000 1100
  769. memory[memoryIndex++] = 0xE331000C;
  770. //End Logic instructions*/
  771. /*Loop instructions*/
  772. //MOV R4,#100 1110 0011 1010 0000 0100 0000 0110 0100
  773. memory[memoryIndex++] = 0xE3A04064;
  774. //MOV R3,#0 1110 0011 1010 0000 0011 0000 0000 0000
  775. memory[memoryIndex++] = 0xE3A03000;
  776. //SUB R4,R4,R3 1110 0000 0100 0100 0100 0000 0000 0011 //.strR4100
  777. memory[memoryIndex++] = 0xE0444003;
  778. //ADD R3,R3,#1 1110 0010 1000 0011 0011 0000 0000 0001
  779. memory[memoryIndex++] = 0xE2833001;
  780. //CMP R3,#100 1110 0011 0101 0011 0000 0000 0110 0100
  781. memory[memoryIndex++] = 0xE3530064;
  782. //BNE #-32 0001 1010 1111 1111 1111 1111 1110 0000 //return to .strR4100 if loop not completed. 4+4 instructions back, because of pipeline
  783. memory[memoryIndex++] = 0x1AFFFFE0;
  784. //End Loop instructions
  785. /*Data transfer instructions
  786. //MOV R0,#10 1110 0011 1010 0000 0000 0000 0000 1010 //Counter for loop = 10
  787. memory[memoryIndex++] = 0xE3A0000A;
  788. //MOV R4,#100 1110 0011 1010 0000 0100 0000 0110 0100
  789. memory[memoryIndex++] = 0xE3A04064;
  790. //MOV R3,#120 1110 0011 1010 0000 0011 0000 0111 1000
  791. memory[memoryIndex++] = 0xE3A03078;
  792. //STR R4,R3,#1! 1110 0110 1110 0011 0100 0000 0000 0001 //Post bit set .strR4100
  793. memory[memoryIndex++] = 0xE6E34001;
  794. //SUBS R0,R0,#1 1110 0010 0101 0000 0000 0000 0000 0001 //Start loop counter
  795. memory[memoryIndex++] = 0xE2500001;
  796. //BNE #-28 0001 1010 1111 1111 1111 1111 1110 0100 //return to .strR4100 if loop not completed. 3+4 instructions back, because of pipeline
  797. memory[memoryIndex++] = 0x1AFFFFE4;
  798. //End Data transfer instructions*/
  799. /*Software Interrupt instructions
  800. //SWI #1 1110 1111 0000 0000 0000 0000 0000 0001 //SWI to Add 10 to R0
  801. memory[memoryIndex++] = 0xEF000001;
  802. //SUBS r0,r0,#10 1110 0010 0101 0000 0000 0000 0000 1010
  803. memory[memoryIndex++] = 0xE250000A;
  804. //End Software Interrupt instructions*/
  805. /*Overflow and Carry instructions
  806. //MOV r0,#9 1110 0011 1010 0000 0000 0000 0000 1001
  807. //memory[memoryIndex++] = 0xE3A00009;
  808. //MOV r1,#255,LSL #15 1110 0011 1010 0000 0001 1111 1111 1111//r1 = 8355840 00000000011111111000000000000000
  809. memory[memoryIndex++] = 0xE3A01FFF;
  810. //MOV r1,r1,LSL #8 1110 0001 1010 0000 0001 0000 1000 0001//r1 = 2139095040 01111111100000000000000000000000
  811. memory[memoryIndex++] = 0xE1A01081;
  812. //ADDS r2,r1,r1 1110 0000 1001 0001 0010 0000 0000 0001//r2 = 4278190080 11111111000000000000000000000000 //causes overflow
  813. memory[memoryIndex++] = 0xE0912001;
  814. //MOV r3,r1,LSL #1 1110 0001 1010 0000 0011 0000 0001 0001//r3 = 4278190080 11111111000000000000000000000000
  815. memory[memoryIndex++] = 0xE1A03011;
  816. //ADDS r4,r3,r1 1110 0000 1001 0011 0100 0000 0000 0001//r4 = 6417285120 (1)01111110100000000000000000000000 //causes carry
  817. memory[memoryIndex++] = 0xE0934001;*/
  818. //End Overflow and Carry instructions
  819. //at the moment this will terminate the main loop (see comments below)
  820. memory[memoryIndex++] = 0;
  821. while(!isFinished)
  822. {
  823. //After each instruction is completed, get user feedback
  824. getFeedback();
  825. // fetch the next instruction. Subtract 4 from the PC, because of the pipeline PC points to 4 instructions forward
  826. inst = memory[(registers[15] - 4)];
  827. //increment the PC(register[15]) to point at the next instruction
  828. registers[15]++;
  829. //Initialise the instruction result values
  830. instResult = INST_VALID;
  831. //Initialise the instruction cycle count to 1, because it will take at least 1 cycle even if the condition is not met
  832. instCycleCount = 1;
  833. if ( inst != 0 ) {
  834. printf("---------- Instruction %d ----------\n", instCount);
  835. decodeAndExecute(inst);
  836. printOutput();
  837. //Update total cycle count
  838. totalCycleCount += instCycleCount;
  839. printf("---------- %d Cycles, end of instruction %d----------\n", instCycleCount, instCount);
  840. //Increase the amount of instructions executed
  841. instCount++;
  842. }
  843. else {
  844. // found an instruction with the value 0
  845. // finish once a 0 hit. Not correct behaviour but good for testing
  846. isFinished = 1;
  847. //Total instruction count doesn't include the finish instruction
  848. printf("========== %d Total cycles for %d instructions ==========\n", totalCycleCount, instCount);
  849. printf("Press enter to exit...\n");
  850. getchar();
  851. }
  852. }
  853. // all ok
  854. return 0;
  855. }