OpenCores
URL https://opencores.org/ocsvn/ion/ion/trunk

Subversion Repositories ion

[/] [ion/] [trunk/] [tools/] [slite/] [src/] [slite.c] - Blame information for rev 57

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ja_rd
/*------------------------------------------------------------------------------
2
* slite.c -- MIPS-I simulator based on Steve Rhoad's "mlite"
3
*
4
* This is a slightly modified version of Steve Rhoad's "mlite" simulator, which
5
* is part of his PLASMA project (original date: 1/31/01).
6
*
7
*-------------------------------------------------------------------------------
8
* Usage:
9
*     slite <code file name> <data file name>
10
*
11
* The program will allocate a chunk of RAM (MEM_SIZE bytes) and map it to
12
* address 0x00000000 of the simulated CPU.
13
* Then it will read the 'code file' (as a big-endian plain binary) onto address
14
* 0x0 of the simulated CPU memory, and 'data file' on address 0x10000.
15
* Finally, will reset the CPU and enter the interactive debugger.
16
*
17
* (Note that the above is only necessary if the system does not have caches,
18
* because of the Harvard architecture. With caches in place, program loading
19
* would be antirely conventional).
20
*
21
* A simulation log file will be dumped to file "sw_sim_log.txt". This log can be
22
* used to compare with an equivalent log dumped by the hardware simulation, as
23
* a simple way to validate the hardware for a given program. See the project
24
* readme files for details.
25
*
26
*-------------------------------------------------------------------------------
27
* KNOWN BUGS:
28
*
29
*-------------------------------------------------------------------------------
30
* @date 2011-jan-16
31
*
32
*-------------------------------------------------------------------------------
33
* COPYRIGHT:    Software placed into the public domain by the author.
34
*               Software 'as is' without warranty.  Author liable for nothing.
35
*
36
* IMPORTANT: Assumes host is little endian.
37
*-----------------------------------------------------------------------------*/
38
 
39
#include <stdio.h>
40 11 ja_rd
#include <stdlib.h>
41
#include <stdint.h>
42 2 ja_rd
#include <string.h>
43
#include <ctype.h>
44
#include <assert.h>
45
 
46 31 ja_rd
/** Set to !=0 to disable file logging (much faster simulation) */
47 2 ja_rd
#define FILE_LOGGING_DISABLED (0)
48
/** Define to enable cache simulation (unimplemented) */
49
//#define ENABLE_CACHE
50 31 ja_rd
 
51
 
52
/*---- Definition of simulated system parameters -----------------------------*/
53
 
54
 
55
#define VECTOR_RESET (0x00000000)
56
#define VECTOR_TRAP  (0x0000003c)
57
 
58
typedef struct s_block {
59
    uint32_t start;
60
    uint32_t size;
61 44 ja_rd
    uint32_t mask;
62 31 ja_rd
    uint8_t  *mem;
63
    char     *name;
64
} t_block;
65
 
66
 
67 44 ja_rd
/* Here's where we define the memory areas (blocks) of the system.
68
   Memory decoding is done in the order the blocks are defined; the address
69
   is anded with field .mask and then compared to field .start. If they match
70
   the address modulo the field .size is used to index the memory block, giving
71
   a 'mirror' effect. All of this simulates the behavior of the actual hardware.
72
   Make sure the blocks don't overlap or the scheme will fail.
73
*/
74 31 ja_rd
 
75
#define NUM_MEM_BLOCKS (2)
76
 
77
t_block default_blocks[NUM_MEM_BLOCKS] = {
78
    /* meant as bootstrap block, though it's read/write */
79 44 ja_rd
    {VECTOR_RESET,  0x00010000, 0xf0000000, NULL, "Boot"},
80 31 ja_rd
    /* main ram block  */
81 44 ja_rd
    {0x80000000,    0x00001000, 0xf0000000, NULL, "Data"}
82 31 ja_rd
};
83
 
84 2 ja_rd
 
85
#define ntohs(A) ( ((A)>>8) | (((A)&0xff)<<8) )
86
#define htons(A) ntohs(A)
87
#define ntohl(A) ( ((A)>>24) | (((A)&0xff0000)>>8) | (((A)&0xff00)<<8) | ((A)<<24) )
88
#define htonl(A) ntohl(A)
89
 
90
/*---- OS-dependent support functions and definitions ------------------------*/
91
#ifndef WIN32
92
//Support for Linux
93
#define putch putchar
94
#include <termios.h>
95
#include <unistd.h>
96
 
97 31 ja_rd
void slite_sleep(unsigned int value){
98
    usleep(value * 1000);
99 2 ja_rd
}
100
 
101 31 ja_rd
int kbhit(void){
102
    struct termios oldt, newt;
103
    struct timeval tv;
104
    fd_set read_fd;
105 2 ja_rd
 
106 31 ja_rd
    tcgetattr(STDIN_FILENO, &oldt);
107
    newt = oldt;
108
    newt.c_lflag &= ~(ICANON | ECHO);
109
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
110
    tv.tv_sec=0;
111
    tv.tv_usec=0;
112
    FD_ZERO(&read_fd);
113
    FD_SET(0,&read_fd);
114
    if(select(1, &read_fd, NULL, NULL, &tv) == -1){
115
        return 0;
116
    }
117
    //tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
118
    if(FD_ISSET(0,&read_fd)){
119
        return 1;
120
    }
121
    return 0;
122 2 ja_rd
}
123
 
124 31 ja_rd
int getch(void){
125
    struct termios oldt, newt;
126
    int ch;
127 2 ja_rd
 
128 31 ja_rd
    tcgetattr(STDIN_FILENO, &oldt);
129
    newt = oldt;
130
    newt.c_lflag &= ~(ICANON | ECHO);
131
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
132
    ch = getchar();
133
    //tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
134
    return ch;
135 2 ja_rd
}
136
#else
137
//Support for Windows
138
#include <conio.h>
139 31 ja_rd
extern void __stdcall Sleep(unsigned long value);
140
 
141
void slite_sleep(unsigned int value){
142
    Sleep(value);
143
}
144
 
145 2 ja_rd
#endif
146
/*---- End of OS-dependent support functions and definitions -----------------*/
147
 
148
/*---- Hardware system parameters --------------------------------------------*/
149
 
150
/* Much of this is a remnant from Plasma's mlite and is  no longer used. */
151
/* FIXME Refactor HW system params */
152
 
153
#define UART_WRITE        0x20000000
154
#define UART_READ         0x20000000
155
#define IRQ_MASK          0x20000010
156
#define IRQ_STATUS        0x20000020
157
#define CONFIG_REG        0x20000070
158
#define MMU_PROCESS_ID    0x20000080
159
#define MMU_FAULT_ADDR    0x20000090
160
#define MMU_TLB           0x200000a0
161
 
162
#define IRQ_UART_READ_AVAILABLE  0x001
163
#define IRQ_UART_WRITE_AVAILABLE 0x002
164
#define IRQ_COUNTER18_NOT        0x004
165
#define IRQ_COUNTER18            0x008
166
#define IRQ_MMU                  0x200
167
 
168 5 ja_rd
/*----------------------------------------------------------------------------*/
169 2 ja_rd
 
170 5 ja_rd
/* These are flags that will be used to notify the main cycle function of any
171
   failed assertions in its subfunctions. */
172
#define ASRT_UNALIGNED_READ         (1<<0)
173
#define ASRT_UNALIGNED_WRITE        (1<<1)
174
 
175
char *assertion_messages[2] = {
176
   "Unaligned read",
177
   "Unaligned write"
178
};
179
 
180
 
181 2 ja_rd
/** Length of debugging jump target queue */
182
#define TRACE_BUFFER_SIZE (32)
183
 
184 31 ja_rd
typedef struct s_trace {
185 2 ja_rd
   unsigned int buf[TRACE_BUFFER_SIZE];   /**< queue of last jump targets */
186
   unsigned int next;                     /**< internal queue head pointer */
187
   FILE *log;                             /**< text log file or NULL */
188
   int pr[32];                            /**< last value of register bank */
189
   int hi, lo, epc;                       /**< last value of internal regs */
190 31 ja_rd
} t_trace;
191 2 ja_rd
 
192 31 ja_rd
typedef struct s_state {
193 5 ja_rd
   unsigned failed_assertions;            /**< assertion bitmap */
194
   unsigned faulty_address;               /**< addr that failed assertion */
195 27 ja_rd
 
196
   int delay_slot;              /**< !=0 if prev. instruction was a branch */
197 5 ja_rd
 
198 2 ja_rd
   int r[32];
199
   int opcode;
200 53 ja_rd
   int pc, pc_next, epc;
201
   uint32_t op_addr;            /**< address of opcode being simulated */
202 2 ja_rd
   unsigned int hi;
203
   unsigned int lo;
204 27 ja_rd
   int status;
205
   unsigned cp0_cause;
206 2 ja_rd
   int userMode;
207
   int processId;
208 53 ja_rd
   int exceptionId;             /**< DEPRECATED, to be removed */
209 2 ja_rd
   int faultAddr;
210
   int irqStatus;
211
   int skip;
212 31 ja_rd
   t_trace t;
213
   //unsigned char *mem;
214
   t_block blocks[NUM_MEM_BLOCKS];
215 2 ja_rd
   int wakeup;
216
   int big_endian;
217 31 ja_rd
} t_state;
218 2 ja_rd
 
219
static char *opcode_string[]={
220
   "SPECIAL","REGIMM","J","JAL","BEQ","BNE","BLEZ","BGTZ",
221
   "ADDI","ADDIU","SLTI","SLTIU","ANDI","ORI","XORI","LUI",
222
   "COP0","COP1","COP2","COP3","BEQL","BNEL","BLEZL","BGTZL",
223
   "?","?","?","?","?","?","?","?",
224
   "LB","LH","LWL","LW","LBU","LHU","LWR","?",
225
   "SB","SH","SWL","SW","?","?","SWR","CACHE",
226
   "LL","LWC1","LWC2","LWC3","?","LDC1","LDC2","LDC3"
227
   "SC","SWC1","SWC2","SWC3","?","SDC1","SDC2","SDC3"
228
};
229
 
230
static char *special_string[]={
231
   "SLL","?","SRL","SRA","SLLV","?","SRLV","SRAV",
232
   "JR","JALR","MOVZ","MOVN","SYSCALL","BREAK","?","SYNC",
233
   "MFHI","MTHI","MFLO","MTLO","?","?","?","?",
234
   "MULT","MULTU","DIV","DIVU","?","?","?","?",
235
   "ADD","ADDU","SUB","SUBU","AND","OR","XOR","NOR",
236
   "?","?","SLT","SLTU","?","DADDU","?","?",
237
   "TGE","TGEU","TLT","TLTU","TEQ","?","TNE","?",
238
   "?","?","?","?","?","?","?","?"
239
};
240
 
241
static char *regimm_string[]={
242
   "BLTZ","BGEZ","BLTZL","BGEZL","?","?","?","?",
243
   "TGEI","TGEIU","TLTI","TLTIU","TEQI","?","TNEI","?",
244
   "BLTZAL","BEQZAL","BLTZALL","BGEZALL","?","?","?","?",
245
   "?","?","?","?","?","?","?","?"
246
};
247
 
248
static unsigned int HWMemory[8];
249
 
250
/*---- Local function prototypes ---------------------------------------------*/
251
 
252
/* Debug and logging */
253 31 ja_rd
void init_trace_buffer(t_state *s, const char *log_file_name);
254
void close_trace_buffer(t_state *s);
255
void dump_trace_buffer(t_state *s);
256
void log_cycle(t_state *s);
257
void log_read(t_state *s, int full_address, int word_value, int size, int log);
258
void log_failed_assertions(t_state *s);
259 2 ja_rd
 
260 31 ja_rd
/* CPU model */
261
void free_cpu(t_state *s);
262 44 ja_rd
int init_cpu(t_state *s);
263 31 ja_rd
void reset_cpu(t_state *s);
264
 
265 2 ja_rd
/* Hardware simulation */
266 31 ja_rd
int mem_read(t_state *s, int size, unsigned int address, int log);
267
void mem_write(t_state *s, int size, unsigned address, unsigned value, int log);
268 53 ja_rd
void start_load(t_state *s, uint32_t addr, int rt, int data);
269 2 ja_rd
 
270 16 ja_rd
 
271 2 ja_rd
/*---- Local functions -------------------------------------------------------*/
272
 
273
/** Log to file a memory read operation (not including target reg change) */
274 31 ja_rd
void log_read(t_state *s, int full_address, int word_value, int size, int log){
275 53 ja_rd
    if(s->t.log!=NULL && log!=0){
276
        fprintf(s->t.log, "(%08X) [%08X] <**>=%08X RD\n",
277
              s->op_addr, full_address, word_value);
278
    }
279 2 ja_rd
}
280
 
281
/** Read memory, optionally logging */
282 31 ja_rd
int mem_read(t_state *s, int size, unsigned int address, int log){
283
    unsigned int value=0, word_value=0, i, ptr;
284
    unsigned int full_address = address;
285 2 ja_rd
 
286 31 ja_rd
    s->irqStatus |= IRQ_UART_WRITE_AVAILABLE;
287
    switch(address){
288
    case UART_READ:
289
        word_value = 0x00000001;
290 53 ja_rd
        //log_read(s, full_address, word_value, size, log);
291 31 ja_rd
        return word_value;
292
        /* FIXME Take input from text file */
293
        /*
294
        if(kbhit()){
295 2 ja_rd
            HWMemory[0] = getch();
296 31 ja_rd
        }
297
        s->irqStatus &= ~IRQ_UART_READ_AVAILABLE; //clear bit
298
        return HWMemory[0];
299
        */
300
    case IRQ_MASK:
301
       return HWMemory[1];
302
    case IRQ_MASK + 4:
303
       slite_sleep(10);
304
       return 0;
305
    case IRQ_STATUS:
306
       /*if(kbhit())
307
          s->irqStatus |= IRQ_UART_READ_AVAILABLE;
308
       return s->irqStatus;
309
       */
310
       /* FIXME Optionally simulate UART TX delay */
311
       word_value = 0x00000003; /* Ready to TX and RX */
312 53 ja_rd
       //log_read(s, full_address, word_value, size, log);
313 31 ja_rd
       return word_value;
314
    case MMU_PROCESS_ID:
315
       return s->processId;
316
    case MMU_FAULT_ADDR:
317
       return s->faultAddr;
318
    }
319
 
320
    /* point ptr to the byte in the block, or NULL is the address is unmapped */
321
    ptr = 0;
322
    for(i=0;i<NUM_MEM_BLOCKS;i++){
323 44 ja_rd
        if((address & s->blocks[i].mask) == s->blocks[i].start){
324
            ptr = (unsigned)(s->blocks[i].mem) +
325
                  ((address - s->blocks[i].start) % s->blocks[i].size);
326 31 ja_rd
            break;
327
        }
328
    }
329
    if(!ptr){
330
        /* address out of mapped blocks: log and return zero */
331
        if(s->t.log!=NULL && log!=0){
332
            fprintf(s->t.log, "(%08X) [%08X] <**>=%08X RD UNMAPPED\n",
333
                s->pc, full_address, 0);
334
        }
335
        return 0;
336
    }
337
 
338
    /* get the whole word */
339
    word_value = *(int*)(ptr&0xfffffffc);
340
    if(s->big_endian){
341
        word_value = ntohl(word_value);
342
    }
343 2 ja_rd
 
344 31 ja_rd
    switch(size){
345
    case 4:
346
        if(address & 3){
347 2 ja_rd
            printf("Unaligned access PC=0x%x address=0x%x\n",
348 31 ja_rd
                (int)s->pc, (int)address);
349
        }
350
        if((address & 3) != 0){
351
            /* unaligned word, log fault */
352 5 ja_rd
            s->failed_assertions |= ASRT_UNALIGNED_READ;
353
            s->faulty_address = address;
354
            address = address & 0xfffffffc;
355 31 ja_rd
        }
356
        value = *(int*)ptr;
357
        if(s->big_endian){
358
            value = ntohl(value);
359
        }
360
        break;
361
    case 2:
362
        if((address & 1) != 0){
363
            /* unaligned halfword, log fault */
364 5 ja_rd
            s->failed_assertions |= ASRT_UNALIGNED_READ;
365
            s->faulty_address = address;
366
            address = address & 0xfffffffe;
367 31 ja_rd
        }
368
        value = *(unsigned short*)ptr;
369
        if(s->big_endian){
370
            value = ntohs((unsigned short)value);
371
        }
372
        break;
373
    case 1:
374
        value = *(unsigned char*)ptr;
375
        break;
376
    default:
377
        /* FIXME this is a bug, should quit */
378
        printf("ERROR");
379
    }
380 2 ja_rd
 
381 53 ja_rd
    //log_read(s, full_address, value, size, log);
382 31 ja_rd
    return(value);
383 2 ja_rd
}
384
 
385
/** Write memory */
386 31 ja_rd
void mem_write(t_state *s, int size, unsigned address, unsigned value, int log){
387
    unsigned int i, ptr, mask, dvalue, b0, b1, b2, b3;
388 2 ja_rd
 
389 31 ja_rd
    if(s->t.log!=NULL){
390
        b0 = value & 0x000000ff;
391
        b1 = value & 0x0000ff00;
392
        b2 = value & 0x00ff0000;
393
        b3 = value & 0xff000000;
394 2 ja_rd
 
395 31 ja_rd
        switch(size){
396
        case 4:  mask = 0x0f;
397
            dvalue = value;
398
            break;
399
        case 2:
400
            if((address&0x2)==0){
401
                mask = 0xc;
402
                dvalue = b1<<16 | b0<<16;
403
            }
404
            else{
405
               mask = 0x3;
406
               dvalue = b1 | b0;
407
            }
408
            break;
409
        case 1:
410
            switch(address%4){
411
            case 0 : mask = 0x8;
412
                dvalue = b0<<24;
413
                break;
414
            case 1 : mask = 0x4;
415
                dvalue = b0<<16;
416
                break;
417
            case 2 : mask = 0x2;
418
                dvalue = b0<<8;
419
                break;
420
            case 3 : mask = 0x1;
421
                dvalue = b0;
422
                break;
423
            }
424
            break;
425
        default:
426 2 ja_rd
            printf("BUG: mem write size invalid (%08x)\n", s->pc);
427
            exit(2);
428 31 ja_rd
        }
429 2 ja_rd
 
430 31 ja_rd
        fprintf(s->t.log, "(%08X) [%08X] |%02X|=%08X WR\n",
431 53 ja_rd
                s->op_addr, address, mask, dvalue);
432 31 ja_rd
    }
433 2 ja_rd
 
434 31 ja_rd
    switch(address){
435
    case UART_WRITE:
436
        putch(value);
437
        fflush(stdout);
438
        return;
439
    case IRQ_MASK:
440
        HWMemory[1] = value;
441
        return;
442
    case IRQ_STATUS:
443
        s->irqStatus = value;
444
        return;
445
    case CONFIG_REG:
446
        return;
447
    case MMU_PROCESS_ID:
448
        //printf("processId=%d\n", value);
449
        s->processId = value;
450
        return;
451
    }
452 2 ja_rd
 
453 31 ja_rd
    //ptr = (unsigned int)s->mem + (address % MEM_SIZE);
454
    if(address >= 0x80000000){
455
        ptr = 1;
456
    }
457
    ptr = 0;
458
    for(i=0;i<NUM_MEM_BLOCKS;i++){
459 44 ja_rd
        if((address & s->blocks[i].mask) == s->blocks[i].start){
460
            ptr = (unsigned)(s->blocks[i].mem) +
461
                            ((address - s->blocks[i].start) % s->blocks[i].size);
462 31 ja_rd
            break;
463
        }
464
    }
465
    if(!ptr){
466
        /* address out of mapped blocks: log and return zero */
467
        if(s->t.log!=NULL && log!=0){
468
            fprintf(s->t.log, "(%08X) [%08X] |%02X|=%08X WR UNMAPPED\n",
469 53 ja_rd
                s->op_addr, address, mask, dvalue);
470 31 ja_rd
        }
471
        return;
472
    }
473 2 ja_rd
 
474 31 ja_rd
    switch(size){
475
    case 4:
476
        if((address & 3) != 0){
477
            /* unaligned word, log fault */
478 5 ja_rd
            s->failed_assertions |= ASRT_UNALIGNED_WRITE;
479
            s->faulty_address = address;
480
            address = address & (~0x03);
481 31 ja_rd
        }
482
        if(s->big_endian){
483
            value = htonl(value);
484
        }
485
        *(int*)ptr = value;
486
        break;
487
    case 2:
488
        if((address & 1) != 0){
489
            /* unaligned halfword, log fault */
490 5 ja_rd
            s->failed_assertions |= ASRT_UNALIGNED_WRITE;
491
            s->faulty_address = address;
492
            address = address & (~0x01);
493 31 ja_rd
        }
494
        if(s->big_endian){
495
            value = htons((unsigned short)value);
496
        }
497
        *(short*)ptr = (unsigned short)value;
498
        break;
499
    case 1:
500
        *(char*)ptr = (unsigned char)value;
501
        break;
502
    default:
503
        /* FIXME this is a bug, should quit */
504
        printf("ERROR");
505
    }
506 2 ja_rd
}
507
 
508
/*---- Optional MMU and cache implementation ---------------------------------*/
509
 
510
/*
511
   The actual core does not have a cache so all of the original Plasma mlite.c
512
   code for cache simulation has been removed.
513
*/
514
 
515
/*---- End optional cache implementation -------------------------------------*/
516
 
517
 
518
/** Simulates MIPS-I multiplier unsigned behavior*/
519
void mult_big(unsigned int a,
520
              unsigned int b,
521
              unsigned int *hi,
522 31 ja_rd
              unsigned int *lo){
523
    unsigned int ahi, alo, bhi, blo;
524
    unsigned int c0, c1, c2;
525
    unsigned int c1_a, c1_b;
526 2 ja_rd
 
527 31 ja_rd
    ahi = a >> 16;
528
    alo = a & 0xffff;
529
    bhi = b >> 16;
530
    blo = b & 0xffff;
531 2 ja_rd
 
532 31 ja_rd
    c0 = alo * blo;
533
    c1_a = ahi * blo;
534
    c1_b = alo * bhi;
535
    c2 = ahi * bhi;
536 2 ja_rd
 
537 31 ja_rd
    c2 += (c1_a >> 16) + (c1_b >> 16);
538
    c1 = (c1_a & 0xffff) + (c1_b & 0xffff) + (c0 >> 16);
539
    c2 += (c1 >> 16);
540
    c0 = (c1 << 16) + (c0 & 0xffff);
541
    *hi = c2;
542
    *lo = c0;
543 2 ja_rd
}
544
 
545
/** Simulates MIPS-I multiplier signed behavior*/
546
void mult_big_signed(int a,
547
                     int b,
548
                     unsigned int *hi,
549 31 ja_rd
                     unsigned int *lo){
550
    int64_t xa, xb, xr, temp;
551
    int32_t rh, rl;
552 11 ja_rd
 
553 31 ja_rd
    xa = a;
554
    xb = b;
555
    xr = xa * xb;
556 11 ja_rd
 
557 31 ja_rd
    temp = (xr >> 32) & 0xffffffff;
558
    rh = temp;
559
    temp = (xr >> 0) & 0xffffffff;
560
    rl = temp;
561 11 ja_rd
 
562 31 ja_rd
    *hi = rh;
563
    *lo = rl;
564 2 ja_rd
}
565
 
566
/** Load data from memory (used to simulate load delay slots) */
567 53 ja_rd
void start_load(t_state *s, uint32_t addr, int rt, int data){
568 31 ja_rd
    /* load delay slot not simulated */
569 53 ja_rd
    log_read(s, addr, data, 1, 1);
570 31 ja_rd
    s->r[rt] = data;
571 2 ja_rd
}
572
 
573
/** Execute one cycle of the CPU (including any interlock stall cycles) */
574 31 ja_rd
void cycle(t_state *s, int show_mode){
575
    unsigned int opcode;
576
    int delay_slot = 0; /* 1 of this instruction is a branch */
577
    unsigned int op, rs, rt, rd, re, func, imm, target;
578
    int trap_cause = 0;
579
    int imm_shift, branch=0, lbranch=2, skip2=0;
580
    int *r=s->r;
581
    unsigned int *u=(unsigned int*)s->r;
582
    unsigned int ptr, epc, rSave;
583 2 ja_rd
 
584 31 ja_rd
    opcode = mem_read(s, 4, s->pc, 0);
585
    op = (opcode >> 26) & 0x3f;
586
    rs = (opcode >> 21) & 0x1f;
587
    rt = (opcode >> 16) & 0x1f;
588
    rd = (opcode >> 11) & 0x1f;
589
    re = (opcode >> 6) & 0x1f;
590
    func = opcode & 0x3f;
591
    imm = opcode & 0xffff;
592
    imm_shift = (((int)(short)imm) << 2) - 4;
593
    target = (opcode << 6) >> 4;
594
    ptr = (short)imm + r[rs];
595
    r[0] = 0;
596
 
597
    /* if we are priting state to console, do it now */
598
    if(show_mode){
599
        printf("%8.8x %8.8x ", s->pc, opcode);
600
        if(op == 0){
601
            printf("%8s ", special_string[func]);
602
        }
603
        else if(op == 1){
604
            printf("%8s ", regimm_string[rt]);
605
        }
606
        else{
607
            printf("%8s ", opcode_string[op]);
608
        }
609 2 ja_rd
 
610 31 ja_rd
        printf("$%2.2d $%2.2d $%2.2d $%2.2d ", rs, rt, rd, re);
611
        printf("%4.4x", imm);
612
        if(show_mode == 1){
613
            printf(" r[%2.2d]=%8.8x r[%2.2d]=%8.8x", rs, r[rs], rt, r[rt]);
614
        }
615
        printf("\n");
616
    }
617
 
618
    /* if we're just showing state to console, quit and don't run instruction */
619
    if(show_mode > 5){
620
        return;
621
    }
622
 
623
    /* epc will point to the victim instruction, i.e. THIS instruction */
624
    epc = s->pc;
625 32 ja_rd
 
626
    /* If we catch a jump instruction jumping to itself, assume we hit the
627
       and of the program and quit. */
628
    if(s->pc == s->pc_next+4){
629
        printf("\n\nEndless loop at 0x%08x\n\n", s->pc-4);
630
        s->wakeup = 1;
631 53 ja_rd
    }
632
    s->op_addr = s->pc;
633 31 ja_rd
    s->pc = s->pc_next;
634
    s->pc_next = s->pc_next + 4;
635
    if(s->skip){
636
        s->skip = 0;
637
        return;
638
    }
639
    rSave = r[rt];
640
 
641
    switch(op){
642
    case 0x00:/*SPECIAL*/
643
        switch(func){
644
        case 0x00:/*SLL*/  r[rd]=r[rt]<<re;          break;
645
        case 0x02:/*SRL*/  r[rd]=u[rt]>>re;          break;
646
        case 0x03:/*SRA*/  r[rd]=r[rt]>>re;          break;
647
        case 0x04:/*SLLV*/ r[rd]=r[rt]<<r[rs];       break;
648
        case 0x06:/*SRLV*/ r[rd]=u[rt]>>r[rs];       break;
649
        case 0x07:/*SRAV*/ r[rd]=r[rt]>>r[rs];       break;
650
        case 0x08:/*JR*/   delay_slot=1;
651
                           s->pc_next=r[rs];         break;
652
        case 0x09:/*JALR*/ delay_slot=1;
653
                           r[rd]=s->pc_next;
654
                           s->pc_next=r[rs]; break;
655
        case 0x0a:/*MOVZ*/ if(!r[rt]) r[rd]=r[rs];   break;  /*IV*/
656
        case 0x0b:/*MOVN*/ if(r[rt]) r[rd]=r[rs];    break;  /*IV*/
657
        case 0x0c:/*SYSCALL*/ trap_cause = 8;
658
                              s->exceptionId=1; break;
659
        case 0x0d:/*BREAK*/   trap_cause = 9;
660
                              s->exceptionId=1; break;
661
        case 0x0f:/*SYNC*/ s->wakeup=1;              break;
662
        case 0x10:/*MFHI*/ r[rd]=s->hi;              break;
663
        case 0x11:/*FTHI*/ s->hi=r[rs];              break;
664
        case 0x12:/*MFLO*/ r[rd]=s->lo;              break;
665
        case 0x13:/*MTLO*/ s->lo=r[rs];              break;
666
        case 0x18:/*MULT*/ mult_big_signed(r[rs],r[rt],&s->hi,&s->lo); break;
667
        case 0x19:/*MULTU*/ mult_big(r[rs],r[rt],&s->hi,&s->lo); break;
668
        case 0x1a:/*DIV*/  s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; break;
669
        case 0x1b:/*DIVU*/ s->lo=u[rs]/u[rt]; s->hi=u[rs]%u[rt]; break;
670
        case 0x20:/*ADD*/  r[rd]=r[rs]+r[rt];        break;
671
        case 0x21:/*ADDU*/ r[rd]=r[rs]+r[rt];        break;
672
        case 0x22:/*SUB*/  r[rd]=r[rs]-r[rt];        break;
673
        case 0x23:/*SUBU*/ r[rd]=r[rs]-r[rt];        break;
674
        case 0x24:/*AND*/  r[rd]=r[rs]&r[rt];        break;
675
        case 0x25:/*OR*/   r[rd]=r[rs]|r[rt];        break;
676
        case 0x26:/*XOR*/  r[rd]=r[rs]^r[rt];        break;
677
        case 0x27:/*NOR*/  r[rd]=~(r[rs]|r[rt]);     break;
678
        case 0x2a:/*SLT*/  r[rd]=r[rs]<r[rt];        break;
679
        case 0x2b:/*SLTU*/ r[rd]=u[rs]<u[rt];        break;
680
        case 0x2d:/*DADDU*/r[rd]=r[rs]+u[rt];        break;
681
        case 0x31:/*TGEU*/ break;
682
        case 0x32:/*TLT*/  break;
683
        case 0x33:/*TLTU*/ break;
684
        case 0x34:/*TEQ*/  break;
685
        case 0x36:/*TNE*/  break;
686
        default: printf("ERROR0(*0x%x~0x%x)\n", s->pc, opcode);
687
           s->wakeup=1;
688
        }
689
        break;
690
    case 0x01:/*REGIMM*/
691
        switch(rt){
692 2 ja_rd
            case 0x10:/*BLTZAL*/ r[31]=s->pc_next;
693
            case 0x00:/*BLTZ*/   branch=r[rs]<0;    break;
694
            case 0x11:/*BGEZAL*/ r[31]=s->pc_next;
695
            case 0x01:/*BGEZ*/   branch=r[rs]>=0;   break;
696
            case 0x12:/*BLTZALL*/r[31]=s->pc_next;
697
            case 0x02:/*BLTZL*/  lbranch=r[rs]<0;   break;
698
            case 0x13:/*BGEZALL*/r[31]=s->pc_next;
699
            case 0x03:/*BGEZL*/  lbranch=r[rs]>=0;  break;
700
            default: printf("ERROR1\n"); s->wakeup=1;
701 31 ja_rd
        }
702
        break;
703
    case 0x03:/*JAL*/    r[31]=s->pc_next;
704
    case 0x02:/*J*/      delay_slot=1;
705
                       s->pc_next=(s->pc&0xf0000000)|target; break;
706
    case 0x04:/*BEQ*/    branch=r[rs]==r[rt];     break;
707
    case 0x05:/*BNE*/    branch=r[rs]!=r[rt];     break;
708
    case 0x06:/*BLEZ*/   branch=r[rs]<=0;         break;
709
    case 0x07:/*BGTZ*/   branch=r[rs]>0;          break;
710
    case 0x08:/*ADDI*/   r[rt]=r[rs]+(short)imm;  break;
711
    case 0x09:/*ADDIU*/  u[rt]=u[rs]+(short)imm;  break;
712
    case 0x0a:/*SLTI*/   r[rt]=r[rs]<(short)imm;  break;
713
    case 0x0b:/*SLTIU*/  u[rt]=u[rs]<(unsigned int)(short)imm; break;
714
    case 0x0c:/*ANDI*/   r[rt]=r[rs]&imm;         break;
715
    case 0x0d:/*ORI*/    r[rt]=r[rs]|imm;         break;
716
    case 0x0e:/*XORI*/   r[rt]=r[rs]^imm;         break;
717
    case 0x0f:/*LUI*/    r[rt]=(imm<<16);         break;
718
    case 0x10:/*COP0*/
719
        if((opcode & (1<<23)) == 0){  //move from CP0
720 27 ja_rd
            if(rd == 12){
721 31 ja_rd
                r[rt]=s->status;
722 27 ja_rd
            }
723
            else if(rd == 13){
724 31 ja_rd
                r[rt]=s->cp0_cause;
725 27 ja_rd
            }
726
            else{
727 31 ja_rd
                r[rt]=s->epc;
728 27 ja_rd
            }
729 31 ja_rd
        }
730
        else{                         //move to CP0
731 2 ja_rd
            s->status=r[rt]&1;
732 31 ja_rd
            if(s->processId && (r[rt]&2)){
733
                s->userMode|=r[rt]&2;
734
                //printf("CpuStatus=%d %d %d\n", r[rt], s->status, s->userMode);
735
                //s->wakeup = 1;
736
                //printf("pc=0x%x\n", epc);
737 2 ja_rd
            }
738 31 ja_rd
        }
739
        break;
740 2 ja_rd
//      case 0x11:/*COP1*/ break;
741
//      case 0x12:/*COP2*/ break;
742
//      case 0x13:/*COP3*/ break;
743 31 ja_rd
    case 0x14:/*BEQL*/  lbranch=r[rs]==r[rt];    break;
744
    case 0x15:/*BNEL*/  lbranch=r[rs]!=r[rt];    break;
745
    case 0x16:/*BLEZL*/ lbranch=r[rs]<=0;        break;
746
    case 0x17:/*BGTZL*/ lbranch=r[rs]>0;         break;
747 2 ja_rd
//      case 0x1c:/*MAD*/  break;   /*IV*/
748 31 ja_rd
    case 0x20:/*LB*/    //r[rt]=(signed char)mem_read(s,1,ptr,1);  break;
749 53 ja_rd
                        start_load(s, ptr, rt,(signed char)mem_read(s,1,ptr,1));
750 31 ja_rd
                        break;
751 2 ja_rd
 
752 31 ja_rd
    case 0x21:/*LH*/    //r[rt]=(signed short)mem_read(s,2,ptr,1); break;
753 53 ja_rd
                        start_load(s, ptr, rt, (signed short)mem_read(s,2,ptr,1));
754 31 ja_rd
                        break;
755
    case 0x22:/*LWL*/   //target=8*(ptr&3);
756
                        //r[rt]=(r[rt]&~(0xffffffff<<target))|
757
                        //      (mem_read(s,4,ptr&~3)<<target); break;
758
                        break;
759
    case 0x23:/*LW*/    //r[rt]=mem_read(s,4,ptr,1);   break;
760 53 ja_rd
                        start_load(s, ptr, rt, mem_read(s,4,ptr,1));
761 31 ja_rd
                        break;
762
    case 0x24:/*LBU*/   //r[rt]=(unsigned char)mem_read(s,1,ptr,1); break;
763 53 ja_rd
                        start_load(s, ptr, rt, (unsigned char)mem_read(s,1,ptr,1));
764 31 ja_rd
                        break;
765
    case 0x25:/*LHU*/   //r[rt]= (unsigned short)mem_read(s,2,ptr,1);
766 53 ja_rd
                        start_load(s, ptr, rt, (unsigned short)mem_read(s,2,ptr,1));
767 31 ja_rd
                        break;
768
    case 0x26:/*LWR*/   //target=32-8*(ptr&3);
769
                        //r[rt]=(r[rt]&~((unsigned int)0xffffffff>>target))|
770
                        //((unsigned int)mem_read(s,4,ptr&~3)>>target);
771
                        break;
772
    case 0x28:/*SB*/    mem_write(s,1,ptr,r[rt],1);  break;
773
    case 0x29:/*SH*/    mem_write(s,2,ptr,r[rt],1);  break;
774
    case 0x2a:/*SWL*/   //mem_write(s,1,ptr,r[rt]>>24);
775
                        //mem_write(s,1,ptr+1,r[rt]>>16);
776
                        //mem_write(s,1,ptr+2,r[rt]>>8);
777
                        //mem_write(s,1,ptr+3,r[rt]); break;
778
    case 0x2b:/*SW*/    mem_write(s,4,ptr,r[rt],1);  break;
779
    case 0x2e:/*SWR*/   break; //FIXME
780
    case 0x2f:/*CACHE*/ break;
781
    case 0x30:/*LL*/    //r[rt]=mem_read(s,4,ptr);   break;
782 53 ja_rd
                        start_load(s, ptr, rt, mem_read(s,4,ptr,1));
783 31 ja_rd
                        break;
784 2 ja_rd
//      case 0x31:/*LWC1*/ break;
785
//      case 0x32:/*LWC2*/ break;
786
//      case 0x33:/*LWC3*/ break;
787
//      case 0x35:/*LDC1*/ break;
788
//      case 0x36:/*LDC2*/ break;
789
//      case 0x37:/*LDC3*/ break;
790
//      case 0x38:/*SC*/     *(int*)ptr=r[rt]; r[rt]=1; break;
791 31 ja_rd
    case 0x38:/*SC*/    mem_write(s,4,ptr,r[rt],1); r[rt]=1; break;
792 2 ja_rd
//      case 0x39:/*SWC1*/ break;
793
//      case 0x3a:/*SWC2*/ break;
794
//      case 0x3b:/*SWC3*/ break;
795
//      case 0x3d:/*SDC1*/ break;
796
//      case 0x3e:/*SDC2*/ break;
797
//      case 0x3f:/*SDC3*/ break;
798 31 ja_rd
    default:
799
        /* FIXME should trap unimplemented opcodes */
800
        printf("ERROR2 address=0x%x opcode=0x%x\n", s->pc, opcode);
801
        s->wakeup=1;
802
    }
803 53 ja_rd
 
804
    /* adjust next PC if this was a ajump instruction */
805 31 ja_rd
    s->pc_next += (branch || lbranch == 1) ? imm_shift : 0;
806
    s->pc_next &= ~3;
807
    s->skip = (lbranch == 0) | skip2;
808 2 ja_rd
 
809 31 ja_rd
    /* If there was trouble (failed assertions), log it */
810
    if(s->failed_assertions!=0){
811
        log_failed_assertions(s);
812
        s->failed_assertions=0;
813
    }
814 5 ja_rd
 
815 31 ja_rd
    /* if there's a delayed load pending, do it now: load reg with memory data*/
816
    /* load delay slots not simulated */
817 2 ja_rd
 
818 31 ja_rd
    /* Handle exceptions */
819
   if(s->exceptionId){
820
        r[rt] = rSave;
821
        s->cp0_cause = (s->delay_slot & 0x1) << 31 | (trap_cause & 0x1f);
822
        /* adjust epc if we (i.e. the victim instruction) are in a delay slot */
823
        if(s->delay_slot){
824 27 ja_rd
        epc = epc - 4;
825 31 ja_rd
        }
826
        s->epc = epc;
827
        s->pc_next = 0x3c;
828
        s->skip = 1;
829
        s->exceptionId = 0;
830
        s->userMode = 0;
831
        //s->wakeup = 1;
832
    }
833 27 ja_rd
 
834 53 ja_rd
    /* if we're NOT showing output to console, log state of CPU to file */
835
    if(!show_mode){
836
        log_cycle(s);
837
    }
838
 
839
 
840
 
841 31 ja_rd
    /* if this instruction was any kind of branch that actually jumped, then
842
       the next instruction will be in a delay slot. Remember it. */
843
    delay_slot = ((lbranch==1) || branch || delay_slot);
844
    s->delay_slot = delay_slot;
845 2 ja_rd
}
846
 
847
/** Dump CPU state to console */
848 31 ja_rd
void show_state(t_state *s){
849
    int i,j;
850
    printf("pid=%d userMode=%d, epc=0x%x\n", s->processId, s->userMode, s->epc);
851
    printf("hi=0x%08x lo=0x%08x\n", s->hi, s->lo);
852
    for(i = 0; i < 4; ++i){
853
        printf("%2.2d ", i * 8);
854
        for(j = 0; j < 8; ++j){
855
            printf("%8.8x ", s->r[i*8+j]);
856
        }
857
        printf("\n");
858
    }
859
    //printf("%8.8lx %8.8lx %8.8lx %8.8lx\n", s->pc, s->pc_next, s->hi, s->lo);
860
    j = s->pc;
861
    for(i = -4; i <= 8; ++i){
862
        printf("%c", i==0 ? '*' : ' ');
863
        s->pc = j + i * 4;
864
        cycle(s, 10);
865
    }
866
    s->pc = j;
867 2 ja_rd
}
868
 
869
/** Show debug monitor prompt and execute user command */
870 31 ja_rd
void do_debug(t_state *s){
871
    int ch;
872
    int i, j=0, watch=0, addr;
873
    s->pc_next = s->pc + 4;
874
    s->skip = 0;
875
    s->wakeup = 0;
876
    show_state(s);
877
    ch = ' ';
878
    for(;;){
879
        if(ch != 'n'){
880
            if(watch){
881
                printf("0x%8.8x=0x%8.8x\n", watch, mem_read(s, 4, watch,0));
882 2 ja_rd
            }
883 31 ja_rd
            printf("1=Debug 2=t_trace 3=Step 4=BreakPt 5=Go 6=Memory ");
884
            printf("7=Watch 8=Jump 9=Quit A=dump > ");
885
        }
886
        ch = getch();
887
        if(ch != 'n'){
888
            printf("\n");
889
        }
890
        switch(ch){
891
        case 'a': case 'A':
892
            dump_trace_buffer(s); break;
893
        case '1': case 'd': case ' ':
894
            cycle(s, 0); show_state(s); break;
895
        case 'n':
896
            cycle(s, 1); break;
897
        case '2': case 't':
898
            cycle(s, 0); printf("*"); cycle(s, 10); break;
899
        case '3': case 's':
900
            printf("Count> ");
901
            scanf("%d", &j);
902
            for(i = 0; i < j; ++i){
903
                cycle(s, 1);
904
            }
905
            show_state(s);
906
            break;
907
        case '4': case 'b':
908
            printf("Line> ");
909
            scanf("%x", &j);
910
            printf("break point=0x%x\n", j);
911
            break;
912
        case '5': case 'g':
913
            s->wakeup = 0;
914 2 ja_rd
            cycle(s, 0);
915 31 ja_rd
            while(s->wakeup == 0){
916
                if(s->pc == j){
917
                    printf("\n\nStop: pc = 0x%08x\n\n", j);
918
                    break;
919
                }
920
                cycle(s, 0);
921
            }
922
            show_state(s);
923
            break;
924
        case 'G':
925
            s->wakeup = 0;
926 2 ja_rd
            cycle(s, 1);
927 31 ja_rd
            while(s->wakeup == 0){
928
                if(s->pc == j){
929
                    break;
930
                }
931
                cycle(s, 1);
932
            }
933
            show_state(s);
934
            break;
935
        case '6': case 'm':
936
            printf("Memory> ");
937
            scanf("%x", &j);
938
            for(i = 0; i < 8; ++i){
939
                printf("%8.8x ", mem_read(s, 4, j+i*4, 0));
940
            }
941
            printf("\n");
942
            break;
943
        case '7': case 'w':
944
            printf("Watch> ");
945
            scanf("%x", &watch);
946
            break;
947
        case '8': case 'j':
948
            printf("Jump> ");
949
            scanf("%x", &addr);
950
            s->pc = addr;
951
            s->pc_next = addr + 4;
952
            show_state(s);
953
            break;
954
        case '9': case 'q':
955
            return;
956
        }
957
    }
958 2 ja_rd
}
959
 
960
/** Read binary code and data files */
961 31 ja_rd
int read_program(t_state *s, uint32_t num_files, char **file_names){
962
    FILE *in;
963 44 ja_rd
    uint32_t bytes, i, files_read=0;
964 2 ja_rd
 
965 31 ja_rd
    for(i=0;i<NUM_MEM_BLOCKS;i++){
966
        if(i<num_files){
967
            in = fopen(file_names[i], "rb");
968
            if(in == NULL){
969 44 ja_rd
                free_cpu(s);
970 31 ja_rd
                printf("Can't open file %s, quitting!\n",file_names[i]);
971
                getch();
972
                return(2);
973
            }
974 2 ja_rd
 
975 31 ja_rd
            bytes = fread(s->blocks[i].mem, 1, s->blocks[i].size, in);
976
            fclose(in);
977
            printf("%-16s [size= %6d, start= 0x%08x]\n",
978
                    s->blocks[i].name,
979
                    bytes,
980
                    s->blocks[i].start);
981
            files_read++;
982
        }
983
        else{
984
            break;
985
        }
986
    }
987
 
988
    if(!files_read){
989 44 ja_rd
        free_cpu(s);
990 31 ja_rd
        printf("No binary object files read, quitting\n");
991 44 ja_rd
        return 0;
992 31 ja_rd
    }
993
 
994 44 ja_rd
    return files_read;
995 2 ja_rd
}
996
 
997
/*----------------------------------------------------------------------------*/
998
 
999 31 ja_rd
int main(int argc,char *argv[]){
1000
    t_state state, *s=&state;
1001 2 ja_rd
 
1002 31 ja_rd
    printf("MIPS-I emulator\n");
1003 44 ja_rd
    if(!init_cpu(s)){
1004
        printf("Trouble allocating memory, quitting!\n");
1005
        getch();
1006
        return 1;
1007
    };
1008 2 ja_rd
 
1009 31 ja_rd
    /* do a minimal check on args */
1010
    if(argc==3 || argc==2){
1011
        /* */
1012
    }
1013
    else{
1014
        printf("Usage:");
1015
        printf("    slite file.exe <bin code file> [<bin data file>]\n");
1016
        return 0;
1017
    }
1018 2 ja_rd
 
1019 44 ja_rd
    if(!read_program(s, argc-1, &(argv[1]))){
1020 31 ja_rd
        return 2;
1021
    }
1022 2 ja_rd
 
1023 31 ja_rd
    init_trace_buffer(s, "sw_sim_log.txt");
1024 2 ja_rd
 
1025 31 ja_rd
    /* NOTE: Original mlite supported loading little-endian code, which this
1026 2 ja_rd
      program doesn't. The endianess-conversion code has been removed.
1027 31 ja_rd
    */
1028 2 ja_rd
 
1029 31 ja_rd
    /* Simulate a CPU reset */
1030
    reset_cpu(s);
1031 2 ja_rd
 
1032 31 ja_rd
    /* Enter debug command interface; will only exit clean with user command */
1033
    do_debug(s);
1034 2 ja_rd
 
1035 31 ja_rd
    /* Close and deallocate everything and quit */
1036
    close_trace_buffer(s);
1037
    free_cpu(s);
1038
    return(0);
1039 2 ja_rd
}
1040
 
1041
/*----------------------------------------------------------------------------*/
1042
 
1043
 
1044 31 ja_rd
void init_trace_buffer(t_state *s, const char *log_file_name){
1045
    int i;
1046 2 ja_rd
 
1047
#if FILE_LOGGING_DISABLED
1048 31 ja_rd
    s->t.log = NULL;
1049
    return;
1050 2 ja_rd
#else
1051 31 ja_rd
    for(i=0;i<TRACE_BUFFER_SIZE;i++){
1052
        s->t.buf[i]=0xffffffff;
1053
    }
1054
    s->t.next = 0;
1055 2 ja_rd
 
1056 31 ja_rd
    /* if file logging is enabled, open log file */
1057
    if(log_file_name!=NULL){
1058
        s->t.log = fopen(log_file_name, "w");
1059
        if(s->t.log==NULL){
1060
            printf("Error opening log file '%s', file logging disabled\n",
1061
                    log_file_name);
1062
        }
1063
    }
1064
    else{
1065
        s->t.log = NULL;
1066
    }
1067 2 ja_rd
#endif
1068
}
1069
 
1070
/** Dumps last jump targets as a chunk of hex numbers (older is left top) */
1071 31 ja_rd
void dump_trace_buffer(t_state *s){
1072
    int i, col;
1073 2 ja_rd
 
1074 31 ja_rd
    for(i=0, col=0;i<TRACE_BUFFER_SIZE;i++, col++){
1075
        printf("%08x ", s->t.buf[s->t.next + i]);
1076
        if((col % 8)==7){
1077
            printf("\n");
1078
        }
1079
    }
1080 2 ja_rd
}
1081
 
1082
/** Logs last cycle's activity (changes in state and/or loads/stores) */
1083 31 ja_rd
void log_cycle(t_state *s){
1084
    static unsigned int last_pc = 0;
1085
    int i;
1086 53 ja_rd
    uint32_t log_pc;
1087 2 ja_rd
 
1088 31 ja_rd
    /* store PC in trace buffer only if there was a jump */
1089
    if(s->pc != (last_pc+4)){
1090
        s->t.buf[s->t.next] = s->pc;
1091
        s->t.next = (s->t.next + 1) % TRACE_BUFFER_SIZE;
1092
    }
1093
    last_pc = s->pc;
1094 2 ja_rd
 
1095 31 ja_rd
    /* if file logging is enabled, dump a trace log to file */
1096
    if(s->t.log!=NULL){
1097 53 ja_rd
        log_pc = s->op_addr;
1098
 
1099 31 ja_rd
        for(i=0;i<32;i++){
1100
            if(s->t.pr[i] != s->r[i]){
1101 53 ja_rd
                fprintf(s->t.log, "(%08X) [%02X]=%08X\n", log_pc, i, s->r[i]);
1102 31 ja_rd
            }
1103
            s->t.pr[i] = s->r[i];
1104
        }
1105
        if(s->lo != s->t.lo){
1106 53 ja_rd
            fprintf(s->t.log, "(%08X) [LO]=%08X\n", log_pc, s->lo);
1107 31 ja_rd
        }
1108
        s->t.lo = s->lo;
1109 2 ja_rd
 
1110 31 ja_rd
        if(s->hi != s->t.hi){
1111 53 ja_rd
            fprintf(s->t.log, "(%08X) [HI]=%08X\n", log_pc, s->hi);
1112 31 ja_rd
        }
1113
        s->t.hi = s->hi;
1114 2 ja_rd
 
1115 53 ja_rd
        /* */
1116
        /* FIXME epc may change by direct write too, handle case */
1117 31 ja_rd
        if(s->epc != s->t.epc){
1118 53 ja_rd
            fprintf(s->t.log, "(%08X) [EP]=%08X\n", log_pc, s->epc);
1119 31 ja_rd
        }
1120
        s->t.epc = s->epc;
1121
    }
1122 2 ja_rd
}
1123
 
1124
/** Frees debug buffers and closes log file */
1125 31 ja_rd
void close_trace_buffer(t_state *s){
1126
    if(s->t.log){
1127
        fclose(s->t.log);
1128
    }
1129 2 ja_rd
}
1130 5 ja_rd
 
1131
/** Logs a message for each failed assertion, each in a line */
1132 31 ja_rd
void log_failed_assertions(t_state *s){
1133
    unsigned bitmap = s->failed_assertions;
1134
    int i = 0;
1135 5 ja_rd
 
1136 31 ja_rd
    /* This loop will crash the program if the message table is too short...*/
1137
    if(s->t.log != NULL){
1138
        for(i=0;i<32;i++){
1139
            if(bitmap & 0x1){
1140
                fprintf(s->t.log, "ASSERTION FAILED: [%08x] %s\n",
1141
                        s->faulty_address,
1142
                        assertion_messages[i]);
1143
            }
1144
            bitmap = bitmap >> 1;
1145
        }
1146
    }
1147 5 ja_rd
}
1148 31 ja_rd
 
1149
void free_cpu(t_state *s){
1150
    int i;
1151
 
1152
    for(i=0;i<NUM_MEM_BLOCKS;i++){
1153
        free(s->blocks[i].mem);
1154
        s->blocks[i].mem = NULL;
1155
 
1156
    }
1157
}
1158
 
1159
void reset_cpu(t_state *s){
1160
    s->pc = VECTOR_RESET;     /* reset start vector */
1161
    s->delay_slot = 0;
1162
    s->failed_assertions = 0; /* no failed assertions pending */
1163
}
1164
 
1165 44 ja_rd
int init_cpu(t_state *s){
1166
    int i, j;
1167
 
1168 31 ja_rd
    memset(s, 0, sizeof(t_state));
1169
    s->big_endian = 1;
1170
    for(i=0;i<NUM_MEM_BLOCKS;i++){
1171
        s->blocks[i].start =  default_blocks[i].start;
1172
        s->blocks[i].size =  default_blocks[i].size;
1173
        s->blocks[i].name =  default_blocks[i].name;
1174 44 ja_rd
        s->blocks[i].mask =  default_blocks[i].mask;
1175
 
1176
        s->blocks[i].mem = (unsigned char*)malloc(s->blocks[i].size);
1177
 
1178
        if(s->blocks[i].mem == NULL){
1179
            for(j=0;j<i;j++){
1180
                free(s->blocks[j].mem);
1181
            }
1182
            return 0;
1183
        }
1184
        memset(s->blocks[i].mem, 0, s->blocks[i].size);
1185 31 ja_rd
    }
1186 44 ja_rd
    return NUM_MEM_BLOCKS;
1187 31 ja_rd
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.