~meshing/meshing/urop

« back to all changes in this revision

Viewing changes to shape/debugger.c

  • Committer: Adam Candy
  • Date: 2013-07-23 18:17:18 UTC
  • Revision ID: adam.candy@imperial.ac.uk-20130723181718-vi35hxtsvopa74z4
Final fix (hopefully).
Licensing formally implemented.  Please update your branches and any derivative works.
Additional tidying and restructure.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
//  
22
22
//////////////////////////////////////////////////////////////////////////
23
23
 
24
 
#include <stdlib.h>
25
 
#include <stdint.h>
26
 
#include <stdio.h>
27
 
#include <assert.h>
28
 
#include <string.h>
29
 
#include <ctype.h>
30
 
 
31
 
#define MIN(a, b) (a > b ? b : a)
32
 
 
33
 
#define MEMORY_SIZE 65536
34
 
#define NUMBER_OF_REGISTERS 32
35
 
#define NUMBER_OF_COMMANDS 12
36
 
#define NUMBER_OF_INSTRUCTIONS 26
37
 
#define BUFFER_SIZE 300      
38
 
#define BREAKPOINTS_ARRAY_SIZE 100
39
 
                
40
 
char debugInstructions[][NUMBER_OF_COMMANDS] = {"list","stp","reg","mem","search","pc", "run", "q","--help","break","back","reset"};
41
 
 
42
 
enum opCodes {HALT, ADD, ADDI, SUB,SUBI,MUL,MULI,LW,SW,BEQ, BNE, BLT, BGT, BLE, 
43
 
                BGE, JMP, JR, JAL, OUT, DIV, DIVI, MOD, MODI, FACT, FACTI,SWAP};
44
 
 
45
 
struct Processor {
46
 
  uint32_t pc;
47
 
  int32_t gpr[NUMBER_OF_REGISTERS];
48
 
  uint8_t memory[MEMORY_SIZE]; 
49
 
};
50
 
 
51
 
//this is a global constant to store the state of the program, i.e. value 1 if program ran.
52
 
int programExitValue;
53
 
 
54
 
/*
55
 
  This method checks if the given tokenn is a register or not.
56
 
  @param token : specifes the token to be checked
57
 
  @return      : returns 1 if the given token is a register
58
 
*/
59
 
int checkRegister(char *token){
60
 
 return (token!=NULL) ? (token[0]=='$') : 0;
61
 
}
62
 
 
63
 
/*
64
 
  This method returns an integer value for the given register
65
 
  @param reg : specifes the reg whose int value has to be returned
66
 
  @return    : returns integer representation of the given string value 
67
 
               representation of the token
68
 
*/
69
 
int getRegisterNumber(char *reg){
70
 
  return atoi(reg+1);
71
 
}
72
 
 
73
 
/*
74
 
  This method checks if a given string is a number.
75
 
  @param num : points to the string to be checked
76
 
  @return    : returns 1 if true, 0 if false
77
 
*/
78
 
 
79
 
int checkIfNumber(char *num) {
80
 
  char *temp = num;
81
 
  while(*temp) {
82
 
    if (!isdigit(*temp)) return 0;
83
 
    temp++;
84
 
  }
85
 
  return 1;
86
 
}
87
 
 
88
 
/*
89
 
  This method prints an "invalid command" error.
90
 
  @param     : takes no parameters
91
 
  @return    : no return value
92
 
*/
93
 
void printInvalidCommandMessage(void) {
94
 
  printf("Invalid command. Please enter --help for help\n");
95
 
}
96
 
 
97
 
/*
98
 
  This method checks if all strings in the given array of strings are registers.
99
 
  @param regs : points to the array of strings to be checked
100
 
  @return     : returns 1 if all strings in the array are register names, 
101
 
                0 otherwise
102
 
*/
103
 
int checkAllRegistersAreValid(char **regs) {
104
 
  while (*regs) {
105
 
    if (!checkRegister(*regs) || !checkIfNumber(*regs+1) || 
106
 
              getRegisterNumber(*regs) <0 || 
107
 
              getRegisterNumber(*regs) >= NUMBER_OF_REGISTERS) {
108
 
      return 0;
109
 
    }
110
 
    regs++;
111
 
  }
112
 
  return 1;
113
 
}
114
 
 
115
 
/*
116
 
  This method returns the value stored in the specified register
117
 
  @param reg  : specifies the register index whose value has to be returned
118
 
  @param proc : specifies the processor from which the value of register has to
119
 
                be returned
120
 
  @return     : returns the value of the register specifed by the index given
121
 
*/
122
 
int32_t getRegisterValue(struct Processor *proc, int8_t reg){
123
 
  return proc->gpr[reg];
124
 
}
125
 
 
126
 
/*
127
 
  This method prints the registers according to the tokens received. The tokens 
128
 
  also contain print modifiers which specify any filters or parameters that the
129
 
  print should satisfy, e.g. "-r" to print through the range of registers that 
130
 
  follows.
131
 
  @param proc: specifies the processor from which the register values are to be
132
 
               returned
133
 
  @param num : points to the array of tokens to be used during the printing
134
 
               process
135
 
  @return    : no return value
136
 
*/
137
 
void printReg(struct Processor *proc , char **tokens) {
138
 
  int start = 0 ;
139
 
  int end = NUMBER_OF_REGISTERS-1;
140
 
  
141
 
  if (strcmp("-r",tokens[0])==0) {
142
 
    start = getRegisterNumber(tokens[1]);
143
 
    end   = getRegisterNumber(tokens[2]);
144
 
    tokens++;
145
 
    if(!start<end && !checkAllRegistersAreValid(tokens+1)){
146
 
      printInvalidCommandMessage();
147
 
      return;
148
 
    }
149
 
    if(tokens[2]!=NULL){
150
 
      printInvalidCommandMessage();
151
 
      return;
152
 
    }
153
 
  }
154
 
  else if (strcmp("-m",tokens[0])==0) {
155
 
    tokens++;
156
 
    if(!checkAllRegistersAreValid(tokens)){
157
 
      printInvalidCommandMessage();
158
 
      return;
159
 
    }
160
 
    int i =0;
161
 
    while(tokens[i]!=NULL) {
162
 
        printf("%s = %i \t",tokens[i],getRegisterValue(proc, getRegisterNumber(tokens[i])));
163
 
        i++;
164
 
      if (i%8==0) printf("      \n");
165
 
    }
166
 
    printf("\n (JVG)");
167
 
    return;    
168
 
  } 
169
 
  else if (!strcmp("-a",tokens[0])==0){
170
 
    printInvalidCommandMessage();
171
 
    return;
172
 
  } 
173
 
 int x=start;
174
 
 printf("%i,%i\n",x, end);
175
 
  for (int i=0; i<end%8 ; i++) {    
176
 
    for (int j=0;j<8 ; j++) {
177
 
      if(x>end) break;
178
 
      printf("$%i = %i \t",x,getRegisterValue(proc,x));
179
 
      x++;
180
 
    }
181
 
    printf("      \n");
182
 
  }  
183
 
}
184
 
/*
185
 
  This method searches the registers for values specified in the tokens 
186
 
  received. The tokens also contain search modifiers which specify any filters
187
 
  or parameters that the search should satisfy, e.g. "-r" to search through the
188
 
  range of registers that follows.
189
 
  @param proc   : specifies the processor from which the register values are to 
190
 
                  be obtained
191
 
  @param tokens : points to the array of tokens to be used during the printing
192
 
                  process
193
 
  @return       : no return value
194
 
*/
195
 
void searchRegisters(struct Processor *proc, char **tokens) {
196
 
  int start =0;
197
 
  int end = NUMBER_OF_REGISTERS-1;
198
 
  if (!checkIfNumber(tokens[1])) {
199
 
    printInvalidCommandMessage();
200
 
    return;
201
 
  }
202
 
  int value = atoi(tokens[1]);
203
 
  
204
 
  if (!checkAllRegistersAreValid(tokens+2)) {
205
 
    printInvalidCommandMessage();
206
 
    return;
207
 
  }
208
 
  
209
 
  if (strcmp(tokens[0],"-r")==0) {
210
 
    start = getRegisterNumber(tokens[2]);
211
 
    end = getRegisterNumber(tokens[3]);
212
 
    if (start>end) {
213
 
      printInvalidCommandMessage();
214
 
      return;
215
 
    }
216
 
    if (tokens[4]!=NULL) {
217
 
       printInvalidCommandMessage();
218
 
       return;
219
 
    }
220
 
  } else if (strcmp(tokens[0],"-a")!=0 || tokens[1]!=NULL) {
221
 
    printInvalidCommandMessage();
222
 
    return;
223
 
  }
224
 
  
225
 
  printf("\n(JVG)");
226
 
  for (int i = start; i<=end ; i++) {
227
 
    if (proc->gpr[i]==value) {
228
 
      printf("$%i=%i  ",i,value);
229
 
    }
230
 
  }
231
 
  printf("\n(JVG)");
232
 
}
233
 
 
234
 
/*
235
 
  This method checks if all strings in the given array of strings are names of 
236
 
  valid memory locations.
237
 
  @param regs : points to the array of strings to be checked
238
 
  @return     : returns 1 if all strings in the array are memory locations, 
239
 
                0 otherwise
240
 
*/
241
 
int checkIfAllMemoryLocationsAreValid(char **tokens) {
242
 
  while(*tokens) {
243
 
    if (!checkIfNumber(*tokens) || atoi(*tokens) <0 
244
 
                || atoi(*tokens)>=MEMORY_SIZE) return 0;
245
 
    tokens++;
246
 
  }
247
 
  return 1;
248
 
}
249
 
/*
250
 
  This method returns the data stored in the memory of the specifed processor
251
 
  at the specified address.
252
 
  @param proc    : specifies the processor 
253
 
  @param address : specifies the address of the memory which data has to be
254
 
                   fetched
255
 
  @return        : returns the value stored in the memory at the specified
256
 
                   address
257
 
*/
258
 
uint32_t getMemory(struct Processor *proc, uint32_t address) {
259
 
  return *(uint32_t *)(proc->memory + address);
260
 
}
261
 
 
262
 
/*
263
 
  This method prints the values memory locations according to the tokens 
264
 
  received. The tokens also contain print modifiers which specify any filters or
265
 
  parameters that the print should satisfy, e.g. "-r" to print through the
266
 
  range of memory locations that follows.
267
 
  @param proc: specifies the processor from which the memory values are to be
268
 
               returned
269
 
  @param num : points to the array of tokens to be used during the printing
270
 
               process
271
 
  @return    : no return value
272
 
*/
273
 
void printMemory(struct Processor *proc, char **tokens) {
274
 
  int start = 0;
275
 
  int end = MEMORY_SIZE-1;
276
 
 
277
 
  if ((strcmp(tokens[0],"-r"))==0) {
278
 
    start = atoi(tokens[1]);
279
 
    end = atoi(tokens[2]);
280
 
    tokens++;
281
 
    if (start>end) {
282
 
      printInvalidCommandMessage();
283
 
      return;
284
 
    }
285
 
    if (tokens[4]!=NULL) {
286
 
       printInvalidCommandMessage();
287
 
       return;
288
 
    }
289
 
  } else if ((strcmp(tokens[0],"-m"))==0) {
290
 
    int j=0;
291
 
    tokens++;
292
 
      if (!checkIfAllMemoryLocationsAreValid(tokens+1)) {
293
 
        printInvalidCommandMessage();
294
 
        return;
295
 
      }
296
 
    while (*tokens) {
297
 
      printf("M%i=%i  ",atoi(*tokens),getMemory(proc,atoi(*tokens)));
298
 
      tokens++;
299
 
      j++;
300
 
      if (j%8==0) printf("\n");
301
 
    }
302
 
    printf("\n (JVG)");
303
 
    return; 
304
 
  } else if ((strcmp(tokens[0],"-a"))!=0) {
305
 
    printInvalidCommandMessage();
306
 
    return;
307
 
  }
308
 
  int x= start;
309
 
  for (int c=0; x<end ; c++) {
310
 
    for (int d=0;d<8&&x<=end ;d++) {
311
 
      printf("M%i=%i \t",x,getMemory(proc,x));
312
 
      x++;
313
 
    }
314
 
    printf("\n");
315
 
  }
316
 
  
317
 
}
318
 
 
319
 
/*
320
 
  This method breaks up a given string into tokens which seperate register
321
 
  values, memory locations, search modifiers, etc
322
 
  @param command: specifies the string to be tokenised
323
 
  @return       : returns an array of strings which can be used as tokens
324
 
*/
325
 
char **tokeniseUserCommand(char *command) {
326
 
  char *buff = malloc(sizeof(char) * BUFFER_SIZE);
327
 
  buff = strncpy(buff,command,sizeof(char) *BUFFER_SIZE);
328
 
  char **tokens = malloc(sizeof(char) *BUFFER_SIZE);
329
 
  char *token = malloc(50);
330
 
  int i=0;
331
 
  token = strtok(buff," ");
332
 
  tokens[i] = token;
333
 
  while(token!=0) {
334
 
    i++;
335
 
    token = strtok(NULL," ");
336
 
    tokens[i] = token;
337
 
  }  
338
 
  return tokens;
339
 
}
340
 
/*
341
 
  This method searches the memory locations for values specified in the tokens 
342
 
  received. The tokens also contain search modifiers which specify any filters
343
 
  or parameters that the search should satisfy, e.g. "-r" to search through the
344
 
  range of memory locations that follows.
345
 
  @param proc   : specifies the processor from which the memory values are to 
346
 
                  be obtained
347
 
  @param tokens : points to the array of tokens to be used during the printing
348
 
                  process
349
 
  @return       : no return value
350
 
*/
351
 
void searchMemory(struct Processor *proc, char **tokens) {
352
 
  int start =0;
353
 
  int end = MEMORY_SIZE-1;
354
 
  if (!checkIfAllMemoryLocationsAreValid(tokens+1)) {
355
 
    printInvalidCommandMessage();
356
 
    return;
357
 
  }
358
 
  int value = atoi(tokens[1]);
359
 
  if (strcmp(tokens[0],"-r")==0) {
360
 
    start = atoi(tokens[2]);
361
 
    end = atoi(tokens[3]);
362
 
    if (start>end) {
363
 
      printInvalidCommandMessage();
364
 
      return;
365
 
    }
366
 
    if (tokens[4]!=NULL) {
367
 
       printInvalidCommandMessage();
368
 
       return;
369
 
    }
370
 
  } 
371
 
  else if (strcmp(tokens[0],"-a")!=0) {
372
 
    printInvalidCommandMessage();
373
 
    return;
374
 
  }
375
 
  printf("\n(JVG)");
376
 
  int x = start;
377
 
  for (int i = start; x<=end ; i++) {
378
 
    if (proc->memory[i]==value) {
379
 
      printf("M%i=%i\t",x,value);
380
 
    }
381
 
    if(i%8==0){
382
 
    printf("\n(JVG)");
383
 
    }
384
 
    x++;
385
 
   }
386
 
  printf("\n(JVG)");
387
 
}
388
 
 
389
 
/*
390
 
  This method begins the search process by checking if the tokens point towards
391
 
  a memory location or a register and calling the required method.
392
 
  @param proc   : specifies the processor to be passed as one of the arguments
393
 
                  to the functions called
394
 
  @param tokens : specifies the tokens to be used in the check
395
 
  @return       : no return value
396
 
*/
397
 
void search(struct Processor *proc,char **tokens) {
398
 
  if (strcmp(tokens[0],"-M") ==0) {
399
 
    printf("mem search\n");
400
 
    searchMemory(proc,tokens+1);
401
 
  } else if (strcmp(tokens[0],"-R")==0) {
402
 
    searchRegisters(proc,tokens+1);
403
 
  }
404
 
}
405
 
 
406
 
/*
407
 
  This method uses an array of integest to check if the line number specified is
408
 
  a break point. 
409
 
  @param breakPoints : points to the integers that indicate the breakpoints
410
 
  @param lineNumber  : specifies the line number
411
 
  @return            : returns 1 if the line number is a break point, 0 if not
412
 
*/
413
 
int checkIfBreakPoint(int *breakPoints, int lineNumber) {
414
 
  for (int i=0; i<BREAKPOINTS_ARRAY_SIZE ;i++) {
415
 
    if (breakPoints[i]==lineNumber) return 1;
416
 
    if (breakPoints[i]==-1) return 0;
417
 
    i++;
418
 
  }
419
 
  return 0;
420
 
}
421
 
/*
422
 
  This method prints the current value of the program counter(PC).
423
 
  @param proc : specifies the processor from which the PC value is to be 
424
 
                obtained
425
 
  @return     : no return value
426
 
*/
427
 
void printPC( struct Processor *proc) {
428
 
  printf("PC = %i \n",proc->pc);
429
 
}
430
 
 
431
 
 
432
 
 
433
 
/*
434
 
  This method returns the opcode (bit 0 to 5) from the given 32 bit instruction
435
 
  @param instruction : This specifies the 32 bit instruction
436
 
  @return            : The method returns 8bit representation of the opcode
437
 
*/
438
 
uint8_t getOpcode(uint32_t instruction) {
439
 
  uint32_t mask = 0xfc000000;
440
 
  uint32_t opcd = mask & instruction;
441
 
  opcd = opcd >> 26;
442
 
  uint8_t opCode = (int) opcd;
443
 
  return opCode;
444
 
}
445
 
 
446
 
/*
447
 
  This method returns the bit 6 to 31 of the given instruction, i.e. the address
448
 
  for j-type instructions
449
 
  @param instruction : this specifies the instruction
450
 
  @return            : the method returns 32 bit representation of the bit 6 to 
451
 
                       31 of the given instruction
452
 
*/
453
 
uint32_t getAddress(uint32_t instruction) {
454
 
  uint32_t mask = 0x03ffffff;
455
 
  return mask & instruction;
456
 
}
457
 
 
458
 
/*
459
 
  This method returns the bit 6 to 10 of the given instruction
460
 
  @param instruction : this specifies the instruction
461
 
  @return            : the method returns 8 bit representation of the bit 6 to 
462
 
                       10 of the given instruction
463
 
*/
464
 
uint8_t getR1(uint32_t instruction){
465
 
  uint32_t mask = 0x03e00000;
466
 
  uint32_t reg = mask & instruction;
467
 
  uint8_t r1 = reg>>21;
468
 
  return r1;
469
 
 
470
 
}
471
 
 
472
 
/*
473
 
  This method returns the bit 11 to 15 of the given instruction
474
 
  @param instruction : this specifies the instruction
475
 
  @return            : the method returns 8 bit representation of the bit 11 to 
476
 
                       15 of the given instruction
477
 
*/
478
 
uint8_t getR2(uint32_t instruction) {
479
 
  uint32_t mask = 0xf8000;
480
 
  uint32_t reg = mask & instruction;
481
 
  uint8_t r2 = reg >> 16;
482
 
  return r2;
483
 
}
484
 
 
485
 
/*
486
 
  This method returns the bit 16 to 21 of the given instruction
487
 
  @param instruction : this specifies the instruction
488
 
  @return            : the method returns 8 bit representation of the bit 16 to 
489
 
                       21 of the given instruction
490
 
*/
491
 
uint8_t getR3(uint32_t instruction) {
492
 
  uint32_t mask = 0x0007C00;
493
 
  return ((mask & instruction) >> 11);
494
 
}
495
 
 
496
 
/*
497
 
  This method returns the bit 16 to 31 of the given instruction
498
 
  @param instruction : this specifies the instruction
499
 
  @return            : the method returns 8 bit representation of the bit 16 to 
500
 
                       31 of the given instruction
501
 
*/
502
 
int16_t getImmediateValue(uint32_t instruction) {
503
 
  uint32_t mask = 0x0000ffff;
504
 
  return (int16_t)(mask & instruction);
505
 
}
506
 
 
507
 
/*
508
 
  This method sets the value of the memory at the specified addredd to the value
509
 
  given.
510
 
  @param proc    : specifies the processor
511
 
  @param address : specifies the address of memory which needs the value to be
512
 
                   set to the given value
513
 
  @param value   : specifies the new value for the memory to be set
514
 
*/
515
 
void setMemory(struct Processor *proc, uint32_t address, int32_t value) {
516
 
  *(uint32_t *)(proc->memory + address) = value;
517
 
}
518
 
 
519
 
/*
520
 
  This method returns the instruction stored in the memory at address specified
521
 
  by the program counter of the processor.
522
 
  @param proc : specifies the processor which contains the program counter,
523
 
                memory, and registers
524
 
*/
525
 
uint32_t getInstructionAtPC(struct Processor *proc){
526
 
  return *(uint32_t *)(proc->memory + proc->pc);
527
 
}
528
 
 
529
 
/*
530
 
  This method prints a segmentation fault error message.
531
 
  @param    : takes no parameters
532
 
  @return   : no return value
533
 
*/
534
 
void printSegmentationFaultMessage(void) {
535
 
  printf("Executing the current line would cause segmentation fault.\n");
536
 
  printf("Please use the 'list' command to track the line where the error occurred\n");
537
 
}
538
 
 
539
 
/*
540
 
  This method checks if the given instruction is a valid R-type instruction.
541
 
  @param ins  : this specifies the instruction
542
 
  @return     : 
543
 
*/
544
 
int checkRtypeInstructionIsValid(uint32_t ins) {
545
 
  uint8_t r1 = getR1(ins);
546
 
  uint8_t r2 = getR2(ins);
547
 
  uint8_t r3 = getR3(ins);
548
 
  if (r1<0 || r2<0 || r3<0 || r1>=NUMBER_OF_REGISTERS || r2>=NUMBER_OF_REGISTERS 
549
 
        || r3>=NUMBER_OF_REGISTERS) {
550
 
    printSegmentationFaultMessage();
551
 
    return 0;
552
 
  }
553
 
  return 1;
554
 
}
555
 
 
556
 
/*
557
 
  This method checks if the given instruction is a valid branch instruction. 
558
 
  @param ins  : specifies the instruction to be used for the check
559
 
  @param proc : specifies the processor which contains the values registers and 
560
 
                program counter
561
 
  @return     : returns 1 if the instruction is a valid branch instruction,
562
 
                0 if not
563
 
*/
564
 
int checkBranchInstructionIsValid(uint32_t ins, struct Processor *proc) {
565
 
  uint8_t r1 = getR1(ins);
566
 
  uint8_t r2 = getR2(ins);
567
 
  int16_t iVal = getImmediateValue(ins);
568
 
  uint32_t pc = proc->pc;
569
 
  if (r1<0 || r2<0 || r1>=NUMBER_OF_REGISTERS || r2>=NUMBER_OF_REGISTERS 
570
 
                                || pc+(iVal*4)<0 || pc+(iVal*4)>=MEMORY_SIZE) {
571
 
    printSegmentationFaultMessage();
572
 
    return 0;
573
 
  }
574
 
  return 1;
575
 
}
576
 
 
577
 
/*
578
 
  This method checks if the given instruction is a valid I-type instruction. 
579
 
  @param ins  : specifies the instruction to be used for the check
580
 
  @return     : returns 1 if the instruction is a valid I-type instruction,
581
 
                0 if not
582
 
*/
583
 
int checkItypeInstructionIsValid(uint32_t ins) {
584
 
  uint8_t r1 = getR1(ins);
585
 
  uint8_t r2 = getR2(ins);
586
 
  if (r1<0 || r2<0 || r1>=NUMBER_OF_REGISTERS || r2>=NUMBER_OF_REGISTERS) {
587
 
    printSegmentationFaultMessage();
588
 
    return 0;
589
 
  }
590
 
  return 1;
591
 
}
592
 
 
593
 
/*
594
 
  This method checks if the given instruction is a valid J-type instruction. 
595
 
  @param ins  : specifies the instruction to be used for the check
596
 
  @return     : returns 1 if the instruction is a valid J-type instruction,
597
 
                0 if not
598
 
*/
599
 
int checkJtypeIsValid(uint32_t ins) {
600
 
  uint32_t add = getAddress(ins);
601
 
  if (add<0 || add>=MEMORY_SIZE) {
602
 
    printSegmentationFaultMessage();
603
 
    return 0;
604
 
  }
605
 
  return 1;
606
 
}
607
 
 
608
 
/*
609
 
  This method checks if the given instruction is a valid "load" or "store" 
610
 
  instruction. 
611
 
  @param ins  : specifies the instruction to be used for the check
612
 
  @return     : returns 1 if the "load"/"store" instruction is valid, 0 if not
613
 
*/
614
 
int checkIfLoadAndStoreAreValid(uint32_t ins) {
615
 
  uint8_t r1 = getR1(ins);
616
 
  uint8_t r2 = getR2(ins);
617
 
  int16_t iVal = getImmediateValue(ins);
618
 
  if (r1<0 || r2<0 || r1>=NUMBER_OF_REGISTERS || r2>=NUMBER_OF_REGISTERS 
619
 
                                        || r2+iVal<0 || r2+iVal>=MEMORY_SIZE) {
620
 
    printSegmentationFaultMessage();
621
 
    return 0;
622
 
  }
623
 
  return 1;
624
 
}
625
 
 
626
 
/*
627
 
  This method checks if the current intruction is valid. 
628
 
  @param processor : specifies the processor which contains the value of the 
629
 
                     program counter
630
 
  @return          : returns 1 if the instruction at PC is a valid instruction,
631
 
                     0 if not
632
 
*/
633
 
int checkIfInstructionIsValid(struct Processor *processor) {
634
 
  uint32_t instruction = getInstructionAtPC(processor);
635
 
  uint8_t opcode = getOpcode(instruction);
636
 
  if (opcode<0 || opcode>NUMBER_OF_INSTRUCTIONS) {
637
 
    printf("The opcode for the current instruction is invalid. This would cause SEGMENTATION FAULT\n");
638
 
    programExitValue =1;
639
 
    return 0;    
640
 
  };
641
 
  switch (opcode)  {
642
 
    case HALT : return 1;
643
 
    case ADD  : return checkRtypeInstructionIsValid(instruction)!=0;
644
 
    case ADDI :return checkItypeInstructionIsValid(instruction)!=0;
645
 
    case SUB  : return checkRtypeInstructionIsValid(instruction)!=0;
646
 
    case SUBI : return checkItypeInstructionIsValid(instruction)!=0;
647
 
    case MUL  : return checkRtypeInstructionIsValid(instruction)!=0;
648
 
    case MULI : return checkItypeInstructionIsValid(instruction)!=0;
649
 
    case LW   : return checkIfLoadAndStoreAreValid(instruction)!=0; 
650
 
    case SW   : return checkIfLoadAndStoreAreValid(instruction)!=0;
651
 
    case BEQ  : return checkBranchInstructionIsValid(instruction,processor)!=0;
652
 
    case BNE  : return checkBranchInstructionIsValid(instruction,processor)!=0; 
653
 
    case BLT  : return checkBranchInstructionIsValid(instruction,processor)!=0;
654
 
    case BGT  : return checkBranchInstructionIsValid(instruction,processor)!=0;
655
 
    case BLE  : return checkBranchInstructionIsValid(instruction,processor)!=0;
656
 
    case BGE  : return checkBranchInstructionIsValid(instruction,processor)!=0;
657
 
    case JMP  : return checkJtypeIsValid(instruction)!=0;
658
 
    case JR   : return checkRtypeInstructionIsValid(instruction)!=0;
659
 
    case JAL  : return checkJtypeIsValid(instruction)!=0;
660
 
    case OUT  : return checkRtypeInstructionIsValid(instruction)!=0;
661
 
    case DIV  : return checkRtypeInstructionIsValid(instruction)!=0;
662
 
    case DIVI : return checkItypeInstructionIsValid(instruction)!=0;
663
 
    case MOD  : return checkRtypeInstructionIsValid(instruction)!=0;
664
 
    case MODI : return checkItypeInstructionIsValid(instruction)!=0;
665
 
    case FACT : return checkRtypeInstructionIsValid(instruction)!=0;
666
 
    case FACTI: return checkItypeInstructionIsValid(instruction)!=0;
667
 
    case SWAP : return checkRtypeInstructionIsValid(instruction)!=0;
668
 
    default   : return 0;
669
 
  }
670
 
}
671
 
/*
672
 
  This method carries out the instruction and returns the integer result of the 
673
 
  operation.
674
 
  @param processor : specifies the processor from which the instruction, 
675
 
                     register and program counter values are to be taken
676
 
  @return          : returns the integer that is the result of the operations
677
 
*/
678
 
int carryOutInstruction(struct Processor *processor) {
679
 
  uint32_t instruction = getInstructionAtPC(processor);
680
 
  uint8_t opcode = getOpcode(instruction);
681
 
  if (opcode<0 || opcode>NUMBER_OF_INSTRUCTIONS) {
682
 
    printf("The opcode for the current instruction is invalid. This would cause SEGMENTATION FAULT\n");
683
 
    programExitValue =1;
684
 
    return 0;    
685
 
  };
686
 
  uint32_t backupPC = processor->pc;
687
 
  int32_t temp;
688
 
  div_t division;
689
 
  switch (opcode)  {
690
 
    case HALT : return 0;
691
 
    case ADD  : if (checkRtypeInstructionIsValid(instruction)==0) return 0;
692
 
                processor->gpr[getR1(instruction)] = 
693
 
                  getRegisterValue(processor, getR2(instruction)) + 
694
 
                  getRegisterValue(processor, getR3(instruction));
695
 
                break;
696
 
                
697
 
    case ADDI : if (checkItypeInstructionIsValid(instruction)==0) return 0;
698
 
                processor->gpr[getR1(instruction)] = 
699
 
                  getRegisterValue(processor, getR2(instruction)) + 
700
 
                  getImmediateValue(instruction);
701
 
                break;
702
 
               
703
 
    case SUB  : if (checkRtypeInstructionIsValid(instruction)==0) return 0;
704
 
                processor->gpr[getR1(instruction)] = 
705
 
                  getRegisterValue(processor, getR2(instruction)) - 
706
 
                  getRegisterValue(processor, getR3(instruction));
707
 
                break;
708
 
                
709
 
    case SUBI : if (checkItypeInstructionIsValid(instruction)==0) return 0;
710
 
                processor->gpr[getR1(instruction)] = 
711
 
                  getRegisterValue(processor, getR2(instruction)) - 
712
 
                   getImmediateValue(instruction);
713
 
                 break;
714
 
                  
715
 
    case MUL  : if (checkRtypeInstructionIsValid(instruction)==0) return 0;
716
 
                processor->gpr[getR1(instruction)] = 
717
 
                  getRegisterValue(processor, getR2(instruction)) * 
718
 
                  getRegisterValue(processor, getR3(instruction));
719
 
                break;
720
 
                  
721
 
    case MULI : if (checkItypeInstructionIsValid(instruction)==0) return 0;
722
 
                processor->gpr[getR1(instruction)] = 
723
 
                  getRegisterValue(processor, getR2(instruction)) * 
724
 
                  getImmediateValue(instruction);
725
 
                break;
726
 
                
727
 
    case LW   : processor->gpr[getR1(instruction)] = 
728
 
                getMemory(processor, 
729
 
                          getRegisterValue(processor, getR2(instruction)) + 
730
 
                                            getImmediateValue(instruction));
731
 
                break;
732
 
                  
733
 
    case SW   : setMemory(processor, getRegisterValue
734
 
                  (processor, getR2(instruction)) + 
735
 
                  getImmediateValue(instruction), 
736
 
                  getRegisterValue(processor, getR1(instruction)));
737
 
                break;
738
 
                
739
 
    case BEQ  : if (checkBranchInstructionIsValid(instruction,processor)==0) 
740
 
                  return 0;
741
 
                if (processor->gpr[getR1(instruction)] == 
742
 
                    processor->gpr[getR2(instruction)]) 
743
 
                  { processor->pc += getImmediateValue(instruction) * 4;};
744
 
                break;
745
 
                  
746
 
    case BNE  : if (checkBranchInstructionIsValid(instruction,processor)==0) 
747
 
                return 0;
748
 
                if (processor->gpr[getR1(instruction)] != 
749
 
                    processor->gpr[getR2(instruction)]) 
750
 
                { processor->pc += getImmediateValue(instruction) * 4;};
751
 
                break;
752
 
                  
753
 
    case BLT  : if (checkBranchInstructionIsValid(instruction,processor)==0) 
754
 
                return 0;
755
 
                if (processor->gpr[getR1(instruction)] <
756
 
                   processor->gpr[getR2(instruction)])
757
 
                { processor->pc += getImmediateValue(instruction) * 4;};
758
 
                break;
759
 
                  
760
 
    case BGT  : if (checkBranchInstructionIsValid(instruction,processor)==0) 
761
 
                return 0;
762
 
                if (processor->gpr[getR1(instruction)] >
763
 
                  processor->gpr[getR2(instruction)]) 
764
 
                { processor->pc += getImmediateValue(instruction) * 4;};
765
 
                break;
766
 
                  
767
 
    case BLE  : if (checkBranchInstructionIsValid(instruction,processor)==0) 
768
 
                  return 0;
769
 
                if (processor->gpr[getR1(instruction)] <= 
770
 
                   processor->gpr[getR2(instruction)]) 
771
 
                { processor->pc += getImmediateValue(instruction) * 4;};
772
 
                break;
773
 
                  
774
 
    case BGE  : if (checkBranchInstructionIsValid(instruction,processor)==0) 
775
 
                return 0;
776
 
                if (processor->gpr[getR1(instruction)] >= 
777
 
                   processor->gpr[getR2(instruction)]) 
778
 
                { processor->pc += (getImmediateValue(instruction) * 4);};
779
 
                break;
780
 
                  
781
 
    case JMP  : if (checkJtypeIsValid(instruction)==0) return 0;
782
 
                processor->pc = getAddress(instruction);
783
 
                break;
784
 
                  
785
 
    case JR   : if (checkRtypeInstructionIsValid(instruction)==0) return 0;
786
 
                processor->pc = getRegisterValue
787
 
                  (processor, getR1(instruction));
788
 
                break;
789
 
                  
790
 
    case JAL  : if (checkJtypeIsValid(instruction)==0) return 0;
791
 
                processor->gpr[31] = processor->pc + sizeof(uint32_t); 
792
 
                processor->pc = getAddress(instruction);
793
 
                break;
794
 
                  
795
 
    case OUT  : if (checkRtypeInstructionIsValid(instruction)==0) return 0;
796
 
                printf("%c", (char)getRegisterValue
797
 
                  (processor, getR1(instruction)));
798
 
                break;
799
 
                  
800
 
    case DIV  : if (checkRtypeInstructionIsValid(instruction)==0) return 0;
801
 
                division = div(getRegisterValue(processor,getR2(instruction))
802
 
                            ,getRegisterValue(processor,getR3(instruction)));
803
 
                processor->gpr[getR1(instruction)] = division.quot;
804
 
     
805
 
    case DIVI : if (checkItypeInstructionIsValid(instruction)==0) return 0;
806
 
                division = div(getRegisterValue(processor,getR2(instruction))
807
 
                            ,getImmediateValue(instruction));
808
 
                processor->gpr[getR1(instruction)] = division.quot;
809
 
      
810
 
    case MOD  : if (checkRtypeInstructionIsValid(instruction)==0) return 0;
811
 
                division = div(getRegisterValue(processor,getR2(instruction))
812
 
                            ,getRegisterValue(processor,getR3(instruction)));
813
 
                processor->gpr[getR1(instruction)] = division.rem;
814
 
      
815
 
    case MODI : if (checkItypeInstructionIsValid(instruction)==0) return 0;
816
 
                division = div(getRegisterValue(processor,getR2(instruction))
817
 
                            ,getImmediateValue(instruction));
818
 
                processor->gpr[getR1(instruction)] = division.rem;
819
 
      
820
 
    case FACT : if (checkRtypeInstructionIsValid(instruction)==0) return 0;
821
 
                processor->gpr[getR1(instruction)] = 
822
 
                getRegisterValue(processor, getR2(instruction));
823
 
                for(int i = 1; i<processor->gpr[getR2(instruction)] ; i++) {
824
 
                  processor->gpr[getR1(instruction)] = 
825
 
                    (getRegisterValue(processor, getR1(instruction)))*
826
 
                    (getRegisterValue(processor, getR2(instruction))-i);
827
 
                }
828
 
                break;
829
 
      
830
 
    case FACTI: if (checkItypeInstructionIsValid(instruction)==0) return 0;
831
 
                processor->gpr[getR1(instruction)] = 
832
 
                getImmediateValue(instruction);
833
 
                for(int i = 1; i<getImmediateValue(instruction) ; i++) {
834
 
                  processor->gpr[getR1(instruction)] = 
835
 
                    (getRegisterValue(processor, getR1(instruction)))*
836
 
                    (getImmediateValue(instruction)-i);
837
 
                }
838
 
                break;
839
 
      
840
 
    case SWAP : if (checkRtypeInstructionIsValid(instruction)==0) return 0;
841
 
                temp = 
842
 
                  getRegisterValue(processor, getR1(instruction));
843
 
                processor->gpr[getR1(instruction)] = 
844
 
                  getRegisterValue(processor, getR2(instruction));
845
 
                processor->gpr[getR2(instruction)] = temp;
846
 
                break;
847
 
  }
848
 
  if(processor->pc == backupPC)  processor->pc += sizeof(uint32_t);
849
 
  return 1;
850
 
}
851
 
 
852
 
/*this method carries out one step 
853
 
@param  : current state of the processor
854
 
@return : a string without the white spaces in it
855
 
*/
856
 
void step(struct Processor *proc) {
857
 
  if (programExitValue==1) {
858
 
    printf("No programs running currently. The previous program has exited already so step cannot be executed\n");
859
 
    return;
860
 
  }
861
 
  int retVal = carryOutInstruction(proc);
862
 
  if (retVal==0) {
863
 
    programExitValue= 1;
864
 
    printf("\n\nProgram exited normally.\n");
865
 
  }
866
 
}
867
 
/*This method removes the space in a string
868
 
@param str : a string which has white space in it
869
 
@return : a string without the white spaces in it
870
 
*/
871
 
char *removeSpace(char *str) {
872
 
  while(*str) {
873
 
    if (isspace((int) *str)==0) return str;
874
 
    str++;
875
 
  }
876
 
  return str;
877
 
}
878
 
 
879
 
/*
880
 
  The method binaryFileLoader loads the binary file in the memory of the given
881
 
  processor.
882
 
  @param processor : this specifes the current processor with the memory to be
883
 
                     initialised with the given instructions from given filepath
884
 
  @param filepath  : this specifies the path of the file which contains the
885
 
                     instructions to be loaded in the memory.
886
 
*/
887
 
void binaryFileLoader(char *filepath, struct Processor *processor) {
888
 
  FILE *fp;
889
 
  fp = fopen(filepath,"rb");
890
 
  if (fp==NULL) {
891
 
    perror("ERROR in opening file");
892
 
    exit(EXIT_FAILURE);
893
 
  }
894
 
 
895
 
  int fileSize;
896
 
  
897
 
  fseek (fp , 0 , SEEK_END);
898
 
  fileSize = ftell (fp);
899
 
  rewind (fp);
900
 
 
901
 
  fileSize = MIN(65536, fileSize);
902
 
 
903
 
  fread(processor->memory, sizeof(uint32_t), fileSize, fp);
904
 
  fclose(fp);
905
 
}
906
 
/* this method is used to get the specific line from the input file
907
 
@param filepath : the path to the file to be searched
908
 
@param n        : the line number to be retrieved
909
 
@return         : returns no specific value however prints out the line if it 
910
 
                  exist or prints End of file reached before line
911
 
 
912
 
*/
913
 
void listInstruction(char *filepath, int n) {
914
 
  FILE *fp;
915
 
  fp = fopen(filepath,"r");
916
 
  char *buffer = (char *) malloc(BUFFER_SIZE * sizeof(char));
917
 
  if (fp==NULL) {
918
 
    perror("ERROR in opening file");
919
 
    exit(EXIT_FAILURE);
920
 
  }
921
 
  while (!feof(fp) &&0<n ){
922
 
    memset(buffer, 0, ((sizeof(char))*BUFFER_SIZE));
923
 
    fgets (buffer, BUFFER_SIZE, fp); 
924
 
    if(strlen(buffer)>1) n--;
925
 
    //printf("%s------n=%i----length =%i\n", buffer,n,strlen(buffer));
926
 
    
927
 
  }
928
 
  if(n==0) {
929
 
    printf("%s", removeSpace(buffer));
930
 
  }
931
 
  else{
932
 
    perror("End of file reached before line");
933
 
  }                  
934
 
  free(buffer);
935
 
  fclose(fp);
936
 
}
937
 
 
938
 
 
939
 
 
940
 
/*
941
 
  This method prints the state of the processor at the end of execution of the
942
 
  program; i.e. the data stored in all the registers and the value of program
943
 
  counter at the end of the program
944
 
  @param proc : this specifies the processor whose state has to be printed
945
 
*/
946
 
void dumpProcessor(struct Processor *proc) {
947
 
  fprintf(stderr, "\n\n-----\n\nPC=%d\n", proc->pc);
948
 
  for(int i = 0; i < 4; i++) {
949
 
    for(int j = 0; j < 8; j++) {
950
 
       int reg = i * 8 + j;
951
 
       fprintf(stderr, "R%d=%d\t", reg, getRegisterValue(proc, reg));
952
 
    }
953
 
      fprintf(stderr, "\n");
954
 
   }
955
 
}
956
 
/*
957
 
  This method prints out the Welcome message at the at the start of the 
958
 
  of the program.
959
 
  @param   :Takes no parameters
960
 
  @return  :Returns no values
961
 
*/
962
 
void printWelcomeMessage(void){
963
 
  FILE *fp;
964
 
  fp = fopen("welcomeMessage.txt","r");
965
 
  char *buffer = (char *) malloc(BUFFER_SIZE * sizeof(char));
966
 
  if (fp==NULL) {
967
 
    perror("ERROR in opening file");
968
 
    exit(EXIT_FAILURE);
969
 
  }
970
 
  while (!feof(fp)){
971
 
    memset(buffer, 0, ((sizeof(char))*BUFFER_SIZE));
972
 
    fgets (buffer, BUFFER_SIZE, fp); 
973
 
    printf("%s",buffer);    
974
 
  }
975
 
}
976
 
/*
977
 
  This method checks whether the user has inputted the right commands for 
978
 
  the program.
979
 
  @param  command: specifies the command to be used in the check
980
 
  @return        : returns 1 if the command is valid and 0 if not
981
 
*/
982
 
int checkUserCommandIsValid(char *command) {
983
 
  for (int i=0; i<NUMBER_OF_COMMANDS; i++) {
984
 
    if (strcmp(command,debugInstructions[i])==0) return 1;
985
 
  }
986
 
  return 0;
987
 
}
988
 
/*
989
 
  This is a method to get a command from the user. Endlessly loops to 
990
 
  continuously get commands from the user until program is quit.
991
 
  @param  : Takes no parameters
992
 
  @return : Returns an array of strings that the user types into the debugger
993
 
            that seem like valid commands
994
 
*/
995
 
char **getUserCommand(void) {
996
 
  printf("(JVG)");
997
 
  char *buff = malloc(BUFFER_SIZE);
998
 
  fgets(buff,BUFFER_SIZE,stdin);
999
 
  char *ptr = malloc(2);
1000
 
  if( (ptr = strchr(buff, '\n')) != NULL) *ptr = '\0';
1001
 
  char **tokens = malloc(sizeof(char) * BUFFER_SIZE);
1002
 
  tokens = tokeniseUserCommand(buff);
1003
 
  if (checkUserCommandIsValid(tokens[0])) return tokens;
1004
 
  printInvalidCommandMessage();
1005
 
  return getUserCommand();
1006
 
}
1007
 
 
1008
 
/*
1009
 
  This is a method to get confirmation from the user of quitting the 
1010
 
  program 
1011
 
  @param  :Takes no parameters
1012
 
  @return :returns 1 if the user wants to quit or 0 otherwise
1013
 
*/
1014
 
int confirmToQuit(void) {
1015
 
  printf("Are you sure you want to quit? enter y for yes and n for no\n(JVG)");
1016
 
  char *ans = malloc(sizeof(char) * BUFFER_SIZE);
1017
 
  fgets(ans,sizeof(char) * BUFFER_SIZE, stdin);
1018
 
  char *ptr = ans;
1019
 
  if( (ptr = strchr(ans, '\n')) != NULL) *ptr = '\0';
1020
 
  int ret = strcmp(ans,"y")==0;
1021
 
  if (ret==0 && strcmp(ans,"n")!=0) {
1022
 
    free(ans);
1023
 
    printf("Please enter a valid answer\n");
1024
 
    return confirmToQuit();
1025
 
  } 
1026
 
  free(ans);
1027
 
  return ret;
1028
 
}
1029
 
 
1030
 
 /*
1031
 
  Runs the piece of code from the current step.
1032
 
  @param proc        : specifies the processor containing the PC values
1033
 
  @param breakPoints : specifies the break points to be checked for in the lines
1034
 
                       of code.
1035
 
  @return            : no return value.
1036
 
 */
1037
 
void run(struct Processor *proc,int *breakPoints) {
1038
 
  if (programExitValue==1) {
1039
 
      printf("No programs running currently. The previous program has exited already so step cannot be executed\n");
1040
 
      return;
1041
 
  }
1042
 
  int retVal = 1;
1043
 
  
1044
 
  do {
1045
 
    retVal = carryOutInstruction(proc);  
1046
 
  } while (retVal && !checkIfBreakPoint(breakPoints,(proc->pc/4)+1));
1047
 
  if (programExitValue==1) return;
1048
 
  if (checkIfBreakPoint(breakPoints,((int) proc->pc/4)+1)==1) {
1049
 
    printf("Breakpoint reached.\n");
1050
 
    return;
1051
 
  }
1052
 
  fflush(stdout);
1053
 
  dumpProcessor(proc);
1054
 
  programExitValue = 1;
1055
 
  printf("\nProgram exited normally.\n");
1056
 
}
1057
 
 
1058
 
/*
1059
 
  This method sets a breakpoint at every occurance of a breakpoint in the given 
1060
 
  tokens. 
1061
 
  @param breakPoints : specifies the line numbers to be used as break points
1062
 
  @param tokens      : specifies the array of strings to be used as the tokens 
1063
 
                       that need to be checked for numbers
1064
 
  @return            : no return value
1065
 
*/
1066
 
void setBreakPoints(int *breakPoints,char **tokens) {
1067
 
  int i=0;
1068
 
  if (strcmp(tokens[0],"-r")==0) {
1069
 
    tokens++;
1070
 
    while(*tokens) {
1071
 
      if (checkIfNumber(*tokens)==0) {
1072
 
        printInvalidCommandMessage();
1073
 
        return;
1074
 
      }
1075
 
      if (breakPoints[i]==atoi(*tokens)) {
1076
 
        breakPoints[i] = -1;
1077
 
      };
1078
 
      if (breakPoints[i] ==-1) {
1079
 
        printInvalidCommandMessage();
1080
 
        printf("breakpoint does not exists");
1081
 
        return;
1082
 
      }
1083
 
      i++;
1084
 
      tokens++;
1085
 
    }
1086
 
  } else if (strcmp(tokens[0],"-a")==0) {
1087
 
    tokens++;
1088
 
    int *temp = malloc(sizeof(int) * BREAKPOINTS_ARRAY_SIZE);
1089
 
    while(*tokens) {
1090
 
      if (checkIfNumber(*tokens)==0) {
1091
 
        printInvalidCommandMessage();
1092
 
        return;
1093
 
      }
1094
 
      temp[i] = atoi(*tokens);
1095
 
      i++;
1096
 
      tokens++;
1097
 
    }
1098
 
    memcpy(breakPoints,temp,sizeof(int) * i);
1099
 
    free(temp);
1100
 
  }
1101
 
}
1102
 
 
1103
 
/*
1104
 
  This method is used to reset the state of the cpu to the state it would
1105
 
  have been in at the start of the program.
1106
 
  @param proc :specifes the current state of the cpu
1107
 
  @param bin  :specifies the filepath of the binary path
1108
 
*/
1109
 
void reset(struct Processor *proc,char *bin) {
1110
 
  memset(proc,0,sizeof(struct Processor));
1111
 
  binaryFileLoader(bin,proc);
1112
 
  programExitValue = 0;
1113
 
}
1114
 
 
1115
 
/*
1116
 
  This method displays the help content in the terminal for the user to get help
1117
 
  @param tokens : specifies the tokens of the given command for help 
1118
 
*/
1119
 
void help(char **tokens){
1120
 
  if(tokens[1]!=NULL){
1121
 
    if(strcmp(tokens[1],"mem") ==0){
1122
 
      system("cat help/mem.txt");
1123
 
      return;
1124
 
    }
1125
 
    else if(strcmp(tokens[1],"reg") ==0){
1126
 
     system("cat help/reg.txt");
1127
 
     return;
1128
 
    }    
1129
 
    else if(strcmp(tokens[1],"search") ==0){
1130
 
     system("cat help/search.txt");
1131
 
     return;
1132
 
    }   
1133
 
  }
1134
 
  system("cat help/help.txt");
1135
 
}
1136
 
 
1137
 
/*
1138
 
  This method is used to execute the user command.
1139
 
  @param assembly    : specifies the assembly instruction to be used
1140
 
  @param bin         : specifies the binary code to be used
1141
 
  @param proc        : specifies the processor that contains the values used
1142
 
  @param tokens      : specifies the tokens to be used to execute the command
1143
 
  @param breakPoints : specifies the various line numbers to be used as break 
1144
 
                       points
1145
 
  @return            : returns 0 when executing any command except confirmation
1146
 
                       of the quit command
1147
 
*/
1148
 
int executeUserCommand(char *assembly, char *bin, struct Processor *proc, 
1149
 
                        char **tokens, int *breakPoints) {
1150
 
  if (strcmp(tokens[0], "reg")==0) {
1151
 
    tokens++;
1152
 
    printReg(proc, tokens);
1153
 
    return 0;
1154
 
  } else if (strcmp(tokens[0], "mem")==0) {
1155
 
    tokens++;
1156
 
    printMemory(proc, tokens);
1157
 
    return 0;
1158
 
  } else if (strcmp(tokens[0], "pc")==0) {
1159
 
    printPC(proc);
1160
 
    return 0;
1161
 
  } else if (strcmp(tokens[0], "search")==0) {
1162
 
    tokens++;
1163
 
    search(proc, tokens);
1164
 
    return 0;
1165
 
  } else if (strcmp(tokens[0], "stp")==0) {
1166
 
    step(proc);
1167
 
    return 0;
1168
 
  } else if (strcmp(tokens[0], "list")==0) {
1169
 
    listInstruction(assembly, ((proc->pc)/4)+1);
1170
 
    return 0;
1171
 
  } else if (strcmp(tokens[0], "--help")==0) {
1172
 
    help(tokens);
1173
 
    return 0;
1174
 
  } else if (strcmp(tokens[0], "run")==0) {
1175
 
    run(proc,breakPoints);
1176
 
    return 0;
1177
 
  } else if (strcmp(tokens[0],"q")==0) {
1178
 
    return confirmToQuit();
1179
 
  } else if (strcmp(tokens[0],"break")==0) {
1180
 
    setBreakPoints(breakPoints,tokens+1);
1181
 
    return 0;
1182
 
  } else if(strcmp(tokens[0],"reset")==0) {
1183
 
    reset(proc,bin);
1184
 
    return 0;
1185
 
  }
1186
 
  return 0;
1187
 
}
1188
 
 
1189
 
int main(int argc, char **argv) {
1190
 
  struct Processor *proc = malloc(sizeof(struct Processor));
1191
 
  assert("There are wrong number of arguents given" && argc==3);
1192
 
  char *fBin = argv[2];
1193
 
  char *fAssembly = argv[1];
1194
 
  memset(proc,0,sizeof(struct Processor));
1195
 
  binaryFileLoader(fBin,proc);
1196
 
  system("clear");
1197
 
  int *breakPoints = malloc(sizeof(int) *BREAKPOINTS_ARRAY_SIZE);
1198
 
  memset(breakPoints,-1,sizeof(int) *BREAKPOINTS_ARRAY_SIZE);
1199
 
  printWelcomeMessage();
1200
 
  char **tokens = malloc(sizeof(char) *BUFFER_SIZE);
1201
 
  int returnVal = 0; 
1202
 
  do {
1203
 
    tokens = getUserCommand();
1204
 
    returnVal = executeUserCommand(fAssembly,fBin,proc,tokens,breakPoints);
1205
 
    free(tokens);
1206
 
  } while (!returnVal);
1207
 
  printf("Thanks for using JVG debugger\n");
1208
 
  system("clear");
1209
 
  free(proc);
1210
 
  free(breakPoints);
1211
 
  return EXIT_SUCCESS;
1212
 
}
 
24
//////////////////////////////////////////////////////////////////////////
 
25
//  
 
26
//  Generation of boundary representation from arbitrary geophysical
 
27
//  fields and initialisation for anisotropic, unstructured meshing.
 
28
//  
 
29
//  Copyright (C) 2011-2013 Dr Adam S. Candy, adam.candy@imperial.ac.uk
 
30
//  
 
31
//  This program is free software: you can redistribute it and/or modify
 
32
//  it under the terms of the GNU General Public License as published by
 
33
//  the Free Software Foundation, either version 3 of the License, or
 
34
//  (at your option) any later version.
 
35
//  
 
36
//  This program is distributed in the hope that it will be useful,
 
37
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
38
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
39
//  GNU General Public License for more details.
 
40
//  
 
41
//  You should have received a copy of the GNU General Public License
 
42
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
43
//  
 
44
//////////////////////////////////////////////////////////////////////////
 
45