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

Subversion Repositories ion

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

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 152 ja_rd
#define R3000_ID (0x00000200)
47
 
48 31 ja_rd
/** Set to !=0 to disable file logging (much faster simulation) */
49 2 ja_rd
#define FILE_LOGGING_DISABLED (0)
50
/** Define to enable cache simulation (unimplemented) */
51
//#define ENABLE_CACHE
52 31 ja_rd
 
53
 
54
/*---- Definition of simulated system parameters -----------------------------*/
55
 
56 61 ja_rd
#define VECTOR_RESET (0xbfc00000)
57
#define VECTOR_TRAP  (0xbfc00180)
58
 
59
/** Definition of a memory block */
60 31 ja_rd
typedef struct s_block {
61
    uint32_t start;
62
    uint32_t size;
63 44 ja_rd
    uint32_t mask;
64 61 ja_rd
    uint32_t read_only;
65 31 ja_rd
    uint8_t  *mem;
66 61 ja_rd
    char     *area_name;
67 31 ja_rd
} t_block;
68 105 ja_rd
 
69
#define NUM_MEM_BLOCKS      (4)
70 152 ja_rd
#define NUM_MEM_MAPS        (4)
71 105 ja_rd
 
72
/** Definition of a memory map */
73
/* FIXME i/o addresses missing, hardcoded */
74
typedef struct s_map {
75
    t_block blocks[NUM_MEM_BLOCKS];
76
} t_map;
77
 
78 31 ja_rd
 
79
 
80 61 ja_rd
/*  Here's where we define the memory areas (blocks) of the system.
81
 
82
    The blocks should be defined in this order: BRAM, XRAM, FLASH
83
 
84
    BRAM is FPGA block ram initialized with bootstrap code
85
    XRAM is external SRAM
86
    FLASH is external flash
87
 
88
    Give any area a size of 0x0 to leave it unused.
89
 
90
    When a binary file is specified in the cmd line for one of these areas, it
91
    will be used to initialize it, checking bounds.
92
 
93
    Memory decoding is done in the order the blocks are defined; the address
94
    is anded with field .mask and then compared to field .start. If they match
95
    the address modulo the field .size is used to index the memory block, giving
96
    a 'mirror' effect. All of this simulates how the actual hardware works.
97
    Make sure the blocks don't overlap or the scheme will fail.
98 44 ja_rd
*/
99 31 ja_rd
 
100 152 ja_rd
#define MAP_DEFAULT         (0)
101
#define MAP_UCLINUX_BRAM    (1)  /* debug only */
102
#define MAP_SMALL           (2)
103
#define MAP_UCLINUX         (3)
104 105 ja_rd
 
105
t_map memory_maps[NUM_MEM_MAPS] = {
106
    {/* Experimental memory map (default) */
107
        {/* Bootstrap BRAM, read only */
108
        {VECTOR_RESET,  0x00004800, 0xf8000000, 1, NULL, "Boot BRAM"},
109
        /* main external ram block  */
110
        {0x00000000,    0x00080000, 0xf8000000, 0, NULL, "XRAM0"},
111
        /* main external ram block  */
112
        {0x80000000,    0x00080000, 0xf8000000, 0, NULL, "XRAM1"},
113
        /* external flash block */
114
        {0xb0000000,    0x00040000, 0xf8000000, 0, NULL, "Flash"},
115
        }
116
    },
117
 
118 152 ja_rd
    {/* uClinux memory map with bootstrap BRAM, debug only, to be removed */
119 105 ja_rd
        {/* Bootstrap BRAM, read only */
120
        {VECTOR_RESET,  0x00001000, 0xf8000000, 1, NULL, "Boot BRAM"},
121
        /* main external ram block  */
122
        {0x80000000,    0x00200000, 0xf8000000, 0, NULL, "XRAM0"},
123
        {0x00000000,    0x00400000, 0xf8000000, 0, NULL, "XRAM1"},
124
        /* external flash block */
125
        {0xb0000000,    0x00100000, 0xf8000000, 0, NULL, "Flash"},
126
        }
127 108 ja_rd
    },
128
 
129
    {/* Experimental memory map with small XRAM */
130
        {/* Bootstrap BRAM, read only */
131
        {VECTOR_RESET,  0x00004800, 0xf8000000, 1, NULL, "Boot BRAM"},
132
        /* main external ram block  */
133
        {0x00000000,    0x00001000, 0xf8000000, 0, NULL, "XRAM0"},
134
        /* main external ram block  */
135
        {0x80000000,    0x00001000, 0xf8000000, 0, NULL, "XRAM1"},
136
        /* external flash block */
137
        {0xb0000000,    0x00040000, 0xf8000000, 0, NULL, "Flash"},
138
        }
139 152 ja_rd
    },
140
 
141
    {/* uClinux memory map with FLASH and XRAM */
142
        {/* Flash mapped at two different addresses is actually meant to be
143
            a single chip (note they have the same size). */
144
         /* E.g. put the bootloader at 0xbfc00000 and the romfs at 0xb0020000;
145
            chip offsets will be 0x0 and 0x20000. */
146
         /* Don't forget there's no address translation here. */
147
        {0xbfc00000,    0x00400000, 0xf8000000, 1, NULL, "Flash (bootloader)"},
148
        {0xb0000000,    0x00400000, 0xf8000000, 1, NULL, "Flash (romfs)"},
149
        /* main external ram block (kernal & user areas ) */
150
        {0x80000000,    0x00200000, 0xf8000000, 0, NULL, "XRAM (kernel)"},
151
        {0x00000000,    0x00400000, 0xf8000000, 0, NULL, "XRAM (user)"},
152
        }
153 105 ja_rd
    },
154 31 ja_rd
};
155 105 ja_rd
 
156 31 ja_rd
 
157 61 ja_rd
/*---- end of system parameters ----------------------------------------------*/
158
 
159
 
160
/** Values for the command line arguments */
161
typedef struct s_args {
162 105 ja_rd
    /** memory map to be used */
163
    uint32_t memory_map;
164
    /** implement unaligned load/stores (don't just trap them) */
165
    uint32_t do_unaligned;
166
    /** start simulation without showing monitor prompt and quit on
167
        end condition -- useful for batch runs */
168
    uint32_t no_prompt;
169
    /** breakpoint address (0xffffffff if unused) */
170
    uint32_t breakpoint;
171
    /** a code fetch from this address starts logging */
172 93 ja_rd
    uint32_t log_trigger_address;
173 105 ja_rd
    /** full name of log file */
174 93 ja_rd
    char *log_file_name;
175 105 ja_rd
    /** bin file to load to each area or null */
176
    char *bin_filename[NUM_MEM_BLOCKS];
177
    /** offset into area (in bytes) where bin wile will be loaded */
178
    uint32_t offset[NUM_MEM_BLOCKS];
179 61 ja_rd
} t_args;
180
/** Parse cmd line args globally accessible */
181
t_args cmd_line_args;
182
 
183
 
184
/*---- Endianess conversion macros -------------------------------------------*/
185 2 ja_rd
 
186
#define ntohs(A) ( ((A)>>8) | (((A)&0xff)<<8) )
187
#define htons(A) ntohs(A)
188
#define ntohl(A) ( ((A)>>24) | (((A)&0xff0000)>>8) | (((A)&0xff00)<<8) | ((A)<<24) )
189
#define htonl(A) ntohl(A)
190
 
191
/*---- OS-dependent support functions and definitions ------------------------*/
192
#ifndef WIN32
193
//Support for Linux
194
#define putch putchar
195
#include <termios.h>
196
#include <unistd.h>
197
 
198 31 ja_rd
void slite_sleep(unsigned int value){
199
    usleep(value * 1000);
200 2 ja_rd
}
201
 
202 31 ja_rd
int kbhit(void){
203
    struct termios oldt, newt;
204
    struct timeval tv;
205
    fd_set read_fd;
206 2 ja_rd
 
207 31 ja_rd
    tcgetattr(STDIN_FILENO, &oldt);
208
    newt = oldt;
209
    newt.c_lflag &= ~(ICANON | ECHO);
210
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
211
    tv.tv_sec=0;
212
    tv.tv_usec=0;
213
    FD_ZERO(&read_fd);
214
    FD_SET(0,&read_fd);
215
    if(select(1, &read_fd, NULL, NULL, &tv) == -1){
216
        return 0;
217
    }
218
    //tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
219
    if(FD_ISSET(0,&read_fd)){
220
        return 1;
221
    }
222
    return 0;
223 2 ja_rd
}
224
 
225 31 ja_rd
int getch(void){
226
    struct termios oldt, newt;
227
    int ch;
228 2 ja_rd
 
229 31 ja_rd
    tcgetattr(STDIN_FILENO, &oldt);
230
    newt = oldt;
231
    newt.c_lflag &= ~(ICANON | ECHO);
232
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
233
    ch = getchar();
234
    //tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
235
    return ch;
236 2 ja_rd
}
237
#else
238
//Support for Windows
239
#include <conio.h>
240 31 ja_rd
extern void __stdcall Sleep(unsigned long value);
241
 
242
void slite_sleep(unsigned int value){
243
    Sleep(value);
244
}
245
 
246 2 ja_rd
#endif
247
/*---- End of OS-dependent support functions and definitions -----------------*/
248
 
249
/*---- Hardware system parameters --------------------------------------------*/
250
 
251
/* Much of this is a remnant from Plasma's mlite and is  no longer used. */
252
/* FIXME Refactor HW system params */
253
 
254 105 ja_rd
#define DBG_REGS          (0x20010000)
255
 
256 2 ja_rd
#define UART_WRITE        0x20000000
257
#define UART_READ         0x20000000
258
#define IRQ_MASK          0x20000010
259
#define IRQ_STATUS        0x20000020
260
#define CONFIG_REG        0x20000070
261
#define MMU_PROCESS_ID    0x20000080
262
#define MMU_FAULT_ADDR    0x20000090
263
#define MMU_TLB           0x200000a0
264
 
265
#define IRQ_UART_READ_AVAILABLE  0x001
266
#define IRQ_UART_WRITE_AVAILABLE 0x002
267
#define IRQ_COUNTER18_NOT        0x004
268
#define IRQ_COUNTER18            0x008
269
#define IRQ_MMU                  0x200
270
 
271 5 ja_rd
/*----------------------------------------------------------------------------*/
272 2 ja_rd
 
273 5 ja_rd
/* These are flags that will be used to notify the main cycle function of any
274
   failed assertions in its subfunctions. */
275
#define ASRT_UNALIGNED_READ         (1<<0)
276
#define ASRT_UNALIGNED_WRITE        (1<<1)
277
 
278
char *assertion_messages[2] = {
279
   "Unaligned read",
280
   "Unaligned write"
281
};
282
 
283
 
284 2 ja_rd
/** Length of debugging jump target queue */
285
#define TRACE_BUFFER_SIZE (32)
286
 
287 31 ja_rd
typedef struct s_trace {
288 2 ja_rd
   unsigned int buf[TRACE_BUFFER_SIZE];   /**< queue of last jump targets */
289
   unsigned int next;                     /**< internal queue head pointer */
290
   FILE *log;                             /**< text log file or NULL */
291 93 ja_rd
   int log_triggered;                     /**< !=0 if log has been triggered */
292
   uint32_t log_trigger_address;          /**< */
293 2 ja_rd
   int pr[32];                            /**< last value of register bank */
294 152 ja_rd
   int hi, lo, epc, status;               /**< last value of internal regs */
295 31 ja_rd
} t_trace;
296 2 ja_rd
 
297 31 ja_rd
typedef struct s_state {
298 5 ja_rd
   unsigned failed_assertions;            /**< assertion bitmap */
299
   unsigned faulty_address;               /**< addr that failed assertion */
300 105 ja_rd
   uint32_t do_unaligned;                 /**< !=0 to enable unaligned L/S */
301
   uint32_t breakpoint;                   /**< BP address of 0xffffffff */
302 27 ja_rd
 
303
   int delay_slot;              /**< !=0 if prev. instruction was a branch */
304 5 ja_rd
 
305 2 ja_rd
   int r[32];
306
   int opcode;
307 53 ja_rd
   int pc, pc_next, epc;
308
   uint32_t op_addr;            /**< address of opcode being simulated */
309 2 ja_rd
   unsigned int hi;
310
   unsigned int lo;
311 27 ja_rd
   int status;
312
   unsigned cp0_cause;
313 2 ja_rd
   int userMode;
314
   int processId;
315 53 ja_rd
   int exceptionId;             /**< DEPRECATED, to be removed */
316 2 ja_rd
   int faultAddr;
317
   int irqStatus;
318
   int skip;
319 31 ja_rd
   t_trace t;
320
   //unsigned char *mem;
321
   t_block blocks[NUM_MEM_BLOCKS];
322 2 ja_rd
   int wakeup;
323
   int big_endian;
324 31 ja_rd
} t_state;
325 2 ja_rd
 
326
static char *opcode_string[]={
327
   "SPECIAL","REGIMM","J","JAL","BEQ","BNE","BLEZ","BGTZ",
328
   "ADDI","ADDIU","SLTI","SLTIU","ANDI","ORI","XORI","LUI",
329
   "COP0","COP1","COP2","COP3","BEQL","BNEL","BLEZL","BGTZL",
330
   "?","?","?","?","?","?","?","?",
331
   "LB","LH","LWL","LW","LBU","LHU","LWR","?",
332
   "SB","SH","SWL","SW","?","?","SWR","CACHE",
333
   "LL","LWC1","LWC2","LWC3","?","LDC1","LDC2","LDC3"
334
   "SC","SWC1","SWC2","SWC3","?","SDC1","SDC2","SDC3"
335
};
336
 
337
static char *special_string[]={
338
   "SLL","?","SRL","SRA","SLLV","?","SRLV","SRAV",
339
   "JR","JALR","MOVZ","MOVN","SYSCALL","BREAK","?","SYNC",
340
   "MFHI","MTHI","MFLO","MTLO","?","?","?","?",
341
   "MULT","MULTU","DIV","DIVU","?","?","?","?",
342
   "ADD","ADDU","SUB","SUBU","AND","OR","XOR","NOR",
343
   "?","?","SLT","SLTU","?","DADDU","?","?",
344
   "TGE","TGEU","TLT","TLTU","TEQ","?","TNE","?",
345
   "?","?","?","?","?","?","?","?"
346
};
347
 
348
static char *regimm_string[]={
349
   "BLTZ","BGEZ","BLTZL","BGEZL","?","?","?","?",
350
   "TGEI","TGEIU","TLTI","TLTIU","TEQI","?","TNEI","?",
351
   "BLTZAL","BEQZAL","BLTZALL","BGEZALL","?","?","?","?",
352
   "?","?","?","?","?","?","?","?"
353
};
354
 
355
static unsigned int HWMemory[8];
356
 
357
/*---- Local function prototypes ---------------------------------------------*/
358
 
359
/* Debug and logging */
360 93 ja_rd
void init_trace_buffer(t_state *s, t_args *args);
361 31 ja_rd
void close_trace_buffer(t_state *s);
362
void dump_trace_buffer(t_state *s);
363
void log_cycle(t_state *s);
364
void log_read(t_state *s, int full_address, int word_value, int size, int log);
365
void log_failed_assertions(t_state *s);
366 93 ja_rd
uint32_t log_enabled(t_state *s);
367
void trigger_log(t_state *s);
368 152 ja_rd
void print_opcode_fields(uint32_t opcode);
369 2 ja_rd
 
370 61 ja_rd
int32_t parse_cmd_line(uint32_t argc, char **argv, t_args *args);
371
void usage(void);
372
 
373 31 ja_rd
/* CPU model */
374
void free_cpu(t_state *s);
375 105 ja_rd
int init_cpu(t_state *s, t_args *args);
376
void reset_cpu(t_state *s);
377
void unimplemented(t_state *s, const char *txt);
378
void reverse_endianess(uint8_t *data, uint32_t bytes);
379 31 ja_rd
 
380 2 ja_rd
/* Hardware simulation */
381 31 ja_rd
int mem_read(t_state *s, int size, unsigned int address, int log);
382
void mem_write(t_state *s, int size, unsigned address, unsigned value, int log);
383 53 ja_rd
void start_load(t_state *s, uint32_t addr, int rt, int data);
384 2 ja_rd
 
385 16 ja_rd
 
386 2 ja_rd
/*---- Local functions -------------------------------------------------------*/
387
 
388
/** Log to file a memory read operation (not including target reg change) */
389 31 ja_rd
void log_read(t_state *s, int full_address, int word_value, int size, int log){
390 147 ja_rd
    /* if bit CP0.16==1, this is a D-Cache line invalidation access and
391
           the HW will not read any actual data, so skip the log (@note1) */
392
    if(log_enabled(s) && log!=0 && !(s->status & 0x00010000)){
393 53 ja_rd
        fprintf(s->t.log, "(%08X) [%08X] <**>=%08X RD\n",
394
              s->op_addr, full_address, word_value);
395
    }
396 2 ja_rd
}
397
 
398
/** Read memory, optionally logging */
399 31 ja_rd
int mem_read(t_state *s, int size, unsigned int address, int log){
400
    unsigned int value=0, word_value=0, i, ptr;
401
    unsigned int full_address = address;
402 2 ja_rd
 
403 31 ja_rd
    s->irqStatus |= IRQ_UART_WRITE_AVAILABLE;
404
    switch(address){
405
    case UART_READ:
406
        /* FIXME Take input from text file */
407 93 ja_rd
        while(!kbhit());
408
        HWMemory[0] = getch();
409
        //s->irqStatus &= ~IRQ_UART_READ_AVAILABLE; //clear bit
410
        printf("%c", HWMemory[0]);
411
        return (HWMemory[0] << 24) | 0x03;
412 31 ja_rd
    case IRQ_MASK:
413
       return HWMemory[1];
414
    case IRQ_MASK + 4:
415
       slite_sleep(10);
416
       return 0;
417
    case IRQ_STATUS:
418
       /*if(kbhit())
419
          s->irqStatus |= IRQ_UART_READ_AVAILABLE;
420
       return s->irqStatus;
421
       */
422
       /* FIXME Optionally simulate UART TX delay */
423
       word_value = 0x00000003; /* Ready to TX and RX */
424 53 ja_rd
       //log_read(s, full_address, word_value, size, log);
425 31 ja_rd
       return word_value;
426
    case MMU_PROCESS_ID:
427
       return s->processId;
428
    case MMU_FAULT_ADDR:
429
       return s->faultAddr;
430
    }
431
 
432
    /* point ptr to the byte in the block, or NULL is the address is unmapped */
433
    ptr = 0;
434
    for(i=0;i<NUM_MEM_BLOCKS;i++){
435 61 ja_rd
        if((address & s->blocks[i].mask) ==
436
           (s->blocks[i].start & s->blocks[i].mask)){
437 44 ja_rd
            ptr = (unsigned)(s->blocks[i].mem) +
438
                  ((address - s->blocks[i].start) % s->blocks[i].size);
439 31 ja_rd
            break;
440
        }
441
    }
442
    if(!ptr){
443
        /* address out of mapped blocks: log and return zero */
444 147 ja_rd
        /* if bit CP0.16==1, this is a D-Cache line invalidation access and
445
           the HW will not read any actual data, so skip the log (@note1) */
446
        if(log_enabled(s) && log!=0 && !(s->status & (1<<16))){
447 31 ja_rd
            fprintf(s->t.log, "(%08X) [%08X] <**>=%08X RD UNMAPPED\n",
448
                s->pc, full_address, 0);
449
        }
450
        return 0;
451
    }
452
 
453
    /* get the whole word */
454
    word_value = *(int*)(ptr&0xfffffffc);
455
    if(s->big_endian){
456
        word_value = ntohl(word_value);
457
    }
458 2 ja_rd
 
459 31 ja_rd
    switch(size){
460
    case 4:
461
        if(address & 3){
462 2 ja_rd
            printf("Unaligned access PC=0x%x address=0x%x\n",
463 31 ja_rd
                (int)s->pc, (int)address);
464
        }
465
        if((address & 3) != 0){
466
            /* unaligned word, log fault */
467 5 ja_rd
            s->failed_assertions |= ASRT_UNALIGNED_READ;
468
            s->faulty_address = address;
469
            address = address & 0xfffffffc;
470 31 ja_rd
        }
471
        value = *(int*)ptr;
472
        if(s->big_endian){
473
            value = ntohl(value);
474
        }
475
        break;
476
    case 2:
477
        if((address & 1) != 0){
478
            /* unaligned halfword, log fault */
479 5 ja_rd
            s->failed_assertions |= ASRT_UNALIGNED_READ;
480
            s->faulty_address = address;
481
            address = address & 0xfffffffe;
482 31 ja_rd
        }
483
        value = *(unsigned short*)ptr;
484
        if(s->big_endian){
485
            value = ntohs((unsigned short)value);
486
        }
487
        break;
488
    case 1:
489
        value = *(unsigned char*)ptr;
490
        break;
491
    default:
492
        /* FIXME this is a bug, should quit */
493
        printf("ERROR");
494
    }
495 2 ja_rd
 
496 53 ja_rd
    //log_read(s, full_address, value, size, log);
497 31 ja_rd
    return(value);
498 2 ja_rd
}
499
 
500
/** Write memory */
501 31 ja_rd
void mem_write(t_state *s, int size, unsigned address, unsigned value, int log){
502
    unsigned int i, ptr, mask, dvalue, b0, b1, b2, b3;
503 2 ja_rd
 
504 93 ja_rd
    if(log_enabled(s)){
505 31 ja_rd
        b0 = value & 0x000000ff;
506
        b1 = value & 0x0000ff00;
507
        b2 = value & 0x00ff0000;
508
        b3 = value & 0xff000000;
509 2 ja_rd
 
510 31 ja_rd
        switch(size){
511
        case 4:  mask = 0x0f;
512
            dvalue = value;
513
            break;
514
        case 2:
515
            if((address&0x2)==0){
516
                mask = 0xc;
517
                dvalue = b1<<16 | b0<<16;
518
            }
519
            else{
520
               mask = 0x3;
521
               dvalue = b1 | b0;
522
            }
523
            break;
524
        case 1:
525
            switch(address%4){
526
            case 0 : mask = 0x8;
527
                dvalue = b0<<24;
528
                break;
529
            case 1 : mask = 0x4;
530
                dvalue = b0<<16;
531
                break;
532
            case 2 : mask = 0x2;
533
                dvalue = b0<<8;
534
                break;
535
            case 3 : mask = 0x1;
536
                dvalue = b0;
537
                break;
538
            }
539
            break;
540
        default:
541 2 ja_rd
            printf("BUG: mem write size invalid (%08x)\n", s->pc);
542
            exit(2);
543 31 ja_rd
        }
544 2 ja_rd
 
545 31 ja_rd
        fprintf(s->t.log, "(%08X) [%08X] |%02X|=%08X WR\n",
546 147 ja_rd
                //s->op_addr, address&0xfffffffc, mask, dvalue);
547
                s->op_addr, address, mask, dvalue);
548 31 ja_rd
    }
549 105 ja_rd
 
550
    if((address&0xffff0000)==DBG_REGS){
551
        printf("[%04x]=%08x\n", address & 0xffff, value);
552
    }
553 2 ja_rd
 
554 31 ja_rd
    switch(address){
555
    case UART_WRITE:
556
        putch(value);
557
        fflush(stdout);
558
        return;
559
    case IRQ_MASK:
560
        HWMemory[1] = value;
561
        return;
562
    case IRQ_STATUS:
563
        s->irqStatus = value;
564
        return;
565
    case CONFIG_REG:
566
        return;
567
    case MMU_PROCESS_ID:
568
        //printf("processId=%d\n", value);
569
        s->processId = value;
570
        return;
571
    }
572 2 ja_rd
 
573 31 ja_rd
    ptr = 0;
574
    for(i=0;i<NUM_MEM_BLOCKS;i++){
575 61 ja_rd
        if((address & s->blocks[i].mask) ==
576
                  (s->blocks[i].start & s->blocks[i].mask)){
577 44 ja_rd
            ptr = (unsigned)(s->blocks[i].mem) +
578
                            ((address - s->blocks[i].start) % s->blocks[i].size);
579 61 ja_rd
 
580
            if(s->blocks[i].read_only){
581 93 ja_rd
                if(log_enabled(s) && log!=0){
582 61 ja_rd
                    fprintf(s->t.log, "(%08X) [%08X] |%02X|=%08X WR READ ONLY\n",
583
                    s->op_addr, address, mask, dvalue);
584
                    return;
585
                }
586
            }
587 31 ja_rd
            break;
588
        }
589
    }
590
    if(!ptr){
591
        /* address out of mapped blocks: log and return zero */
592 93 ja_rd
        if(log_enabled(s) && log!=0){
593 31 ja_rd
            fprintf(s->t.log, "(%08X) [%08X] |%02X|=%08X WR UNMAPPED\n",
594 53 ja_rd
                s->op_addr, address, mask, dvalue);
595 31 ja_rd
        }
596
        return;
597
    }
598 2 ja_rd
 
599 31 ja_rd
    switch(size){
600
    case 4:
601
        if((address & 3) != 0){
602
            /* unaligned word, log fault */
603 5 ja_rd
            s->failed_assertions |= ASRT_UNALIGNED_WRITE;
604
            s->faulty_address = address;
605
            address = address & (~0x03);
606 31 ja_rd
        }
607
        if(s->big_endian){
608
            value = htonl(value);
609
        }
610
        *(int*)ptr = value;
611
        break;
612
    case 2:
613
        if((address & 1) != 0){
614
            /* unaligned halfword, log fault */
615 5 ja_rd
            s->failed_assertions |= ASRT_UNALIGNED_WRITE;
616
            s->faulty_address = address;
617
            address = address & (~0x01);
618 31 ja_rd
        }
619
        if(s->big_endian){
620
            value = htons((unsigned short)value);
621
        }
622
        *(short*)ptr = (unsigned short)value;
623
        break;
624
    case 1:
625
        *(char*)ptr = (unsigned char)value;
626
        break;
627
    default:
628
        /* FIXME this is a bug, should quit */
629
        printf("ERROR");
630
    }
631 2 ja_rd
}
632
 
633 105 ja_rd
/*-- unaligned store and load instructions -----------------------------------*/
634
/*
635
 These are meant to be left unimplemented and trapped. These functions simulate
636
 the unaligned r/w instructions until proper trap handlers are written.
637
*/
638
 
639
void mem_swl(t_state *s, uint32_t address, uint32_t value, uint32_t log){
640
    uint32_t data, offset;
641
 
642
    if(!s->do_unaligned) return unimplemented(s, "SWL");
643
 
644
    offset = (address & 0x03);
645
    address = (address & (~0x03));
646
    data = value;
647
 
648
    while(offset<4){
649
        mem_write(s,1,address+offset,(data>>24) & 0xff,0);
650
        data = data << 8;
651
        offset++;
652
    }
653
}
654
 
655
void mem_swr(t_state *s, uint32_t address, uint32_t value, uint32_t log){
656
    uint32_t data, offset;
657
 
658
    if(!s->do_unaligned) return unimplemented(s, "SWR");
659
 
660
    offset = (address & 0x03);
661
    address = (address & (~0x03));
662
    data = value;
663
 
664
    while(offset>=0){
665
        mem_write(s,1,address+offset,data & 0xff,0);
666
        data = data >> 8;
667
        offset--;
668
    }
669
}
670
 
671
void mem_lwr(t_state *s, uint32_t address, uint32_t reg_index, uint32_t log){
672
    uint32_t offset, data;
673
    uint32_t disp[4] = {24,         16,         8,          0};
674
    uint32_t mask[4] = {0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff};
675
 
676
    if(!s->do_unaligned) return unimplemented(s, "LWR");
677
 
678
    offset = (address & 0x03);
679
    address = (address & (~0x03));
680
 
681
    data = mem_read(s, 4, address, 0);
682
    data = (data >> disp[offset]) & mask[offset];
683
 
684
    s->r[reg_index] = (s->r[reg_index] & (~mask[offset])) | data;
685
}
686
 
687
void mem_lwl(t_state *s, uint32_t address, uint32_t reg_index, uint32_t log){
688
    uint32_t offset, data;
689
    uint32_t disp[4] = {0,          8,          16,         24};
690
    uint32_t mask[4] = {0xffffffff, 0xffffff00, 0xffff0000, 0xff000000};
691
 
692
    if(!s->do_unaligned) return unimplemented(s, "LWL");
693
 
694
    offset = (address & 0x03);
695
    address = (address & (~0x03));
696
 
697
    data = mem_read(s, 4, address, 0);
698
    data = (data << disp[offset]) & mask[offset];
699
 
700
    s->r[reg_index] = (s->r[reg_index] & (~mask[offset])) | data;
701
}
702
 
703
 
704 2 ja_rd
/*---- Optional MMU and cache implementation ---------------------------------*/
705
 
706
/*
707
   The actual core does not have a cache so all of the original Plasma mlite.c
708
   code for cache simulation has been removed.
709
*/
710
 
711
/*---- End optional cache implementation -------------------------------------*/
712
 
713
 
714
/** Simulates MIPS-I multiplier unsigned behavior*/
715
void mult_big(unsigned int a,
716
              unsigned int b,
717
              unsigned int *hi,
718 31 ja_rd
              unsigned int *lo){
719
    unsigned int ahi, alo, bhi, blo;
720
    unsigned int c0, c1, c2;
721
    unsigned int c1_a, c1_b;
722 2 ja_rd
 
723 31 ja_rd
    ahi = a >> 16;
724
    alo = a & 0xffff;
725
    bhi = b >> 16;
726
    blo = b & 0xffff;
727 2 ja_rd
 
728 31 ja_rd
    c0 = alo * blo;
729
    c1_a = ahi * blo;
730
    c1_b = alo * bhi;
731
    c2 = ahi * bhi;
732 2 ja_rd
 
733 31 ja_rd
    c2 += (c1_a >> 16) + (c1_b >> 16);
734
    c1 = (c1_a & 0xffff) + (c1_b & 0xffff) + (c0 >> 16);
735
    c2 += (c1 >> 16);
736
    c0 = (c1 << 16) + (c0 & 0xffff);
737
    *hi = c2;
738
    *lo = c0;
739 2 ja_rd
}
740
 
741
/** Simulates MIPS-I multiplier signed behavior*/
742
void mult_big_signed(int a,
743
                     int b,
744
                     unsigned int *hi,
745 31 ja_rd
                     unsigned int *lo){
746
    int64_t xa, xb, xr, temp;
747
    int32_t rh, rl;
748 11 ja_rd
 
749 31 ja_rd
    xa = a;
750
    xb = b;
751
    xr = xa * xb;
752 11 ja_rd
 
753 31 ja_rd
    temp = (xr >> 32) & 0xffffffff;
754
    rh = temp;
755
    temp = (xr >> 0) & 0xffffffff;
756
    rl = temp;
757 11 ja_rd
 
758 31 ja_rd
    *hi = rh;
759
    *lo = rl;
760 2 ja_rd
}
761
 
762
/** Load data from memory (used to simulate load delay slots) */
763 53 ja_rd
void start_load(t_state *s, uint32_t addr, int rt, int data){
764 31 ja_rd
    /* load delay slot not simulated */
765 53 ja_rd
    log_read(s, addr, data, 1, 1);
766 31 ja_rd
    s->r[rt] = data;
767 2 ja_rd
}
768
 
769
/** Execute one cycle of the CPU (including any interlock stall cycles) */
770 31 ja_rd
void cycle(t_state *s, int show_mode){
771
    unsigned int opcode;
772
    int delay_slot = 0; /* 1 of this instruction is a branch */
773
    unsigned int op, rs, rt, rd, re, func, imm, target;
774
    int trap_cause = 0;
775
    int imm_shift, branch=0, lbranch=2, skip2=0;
776
    int *r=s->r;
777
    unsigned int *u=(unsigned int*)s->r;
778
    unsigned int ptr, epc, rSave;
779 2 ja_rd
 
780 93 ja_rd
    /* fetch and decode instruction */
781 31 ja_rd
    opcode = mem_read(s, 4, s->pc, 0);
782
    op = (opcode >> 26) & 0x3f;
783
    rs = (opcode >> 21) & 0x1f;
784
    rt = (opcode >> 16) & 0x1f;
785
    rd = (opcode >> 11) & 0x1f;
786
    re = (opcode >> 6) & 0x1f;
787
    func = opcode & 0x3f;
788
    imm = opcode & 0xffff;
789
    imm_shift = (((int)(short)imm) << 2) - 4;
790
    target = (opcode << 6) >> 4;
791
    ptr = (short)imm + r[rs];
792
    r[0] = 0;
793
 
794 93 ja_rd
    /* Trigger log if we fetch from trigger address */
795
    if(s->pc == s->t.log_trigger_address){
796
        trigger_log(s);
797
    }
798
 
799 31 ja_rd
    /* if we are priting state to console, do it now */
800
    if(show_mode){
801
        printf("%8.8x %8.8x ", s->pc, opcode);
802
        if(op == 0){
803
            printf("%8s ", special_string[func]);
804
        }
805
        else if(op == 1){
806
            printf("%8s ", regimm_string[rt]);
807
        }
808
        else{
809
            printf("%8s ", opcode_string[op]);
810
        }
811 2 ja_rd
 
812 31 ja_rd
        printf("$%2.2d $%2.2d $%2.2d $%2.2d ", rs, rt, rd, re);
813
        printf("%4.4x", imm);
814
        if(show_mode == 1){
815
            printf(" r[%2.2d]=%8.8x r[%2.2d]=%8.8x", rs, r[rs], rt, r[rt]);
816
        }
817
        printf("\n");
818
    }
819
 
820
    /* if we're just showing state to console, quit and don't run instruction */
821
    if(show_mode > 5){
822
        return;
823
    }
824
 
825
    /* epc will point to the victim instruction, i.e. THIS instruction */
826
    epc = s->pc;
827 32 ja_rd
 
828
    /* If we catch a jump instruction jumping to itself, assume we hit the
829
       and of the program and quit. */
830
    if(s->pc == s->pc_next+4){
831
        printf("\n\nEndless loop at 0x%08x\n\n", s->pc-4);
832
        s->wakeup = 1;
833 53 ja_rd
    }
834
    s->op_addr = s->pc;
835 31 ja_rd
    s->pc = s->pc_next;
836
    s->pc_next = s->pc_next + 4;
837
    if(s->skip){
838
        s->skip = 0;
839
        return;
840
    }
841
    rSave = r[rt];
842
 
843
    switch(op){
844
    case 0x00:/*SPECIAL*/
845
        switch(func){
846
        case 0x00:/*SLL*/  r[rd]=r[rt]<<re;          break;
847
        case 0x02:/*SRL*/  r[rd]=u[rt]>>re;          break;
848
        case 0x03:/*SRA*/  r[rd]=r[rt]>>re;          break;
849
        case 0x04:/*SLLV*/ r[rd]=r[rt]<<r[rs];       break;
850
        case 0x06:/*SRLV*/ r[rd]=u[rt]>>r[rs];       break;
851
        case 0x07:/*SRAV*/ r[rd]=r[rt]>>r[rs];       break;
852
        case 0x08:/*JR*/   delay_slot=1;
853
                           s->pc_next=r[rs];         break;
854
        case 0x09:/*JALR*/ delay_slot=1;
855
                           r[rd]=s->pc_next;
856
                           s->pc_next=r[rs]; break;
857
        case 0x0a:/*MOVZ*/ if(!r[rt]) r[rd]=r[rs];   break;  /*IV*/
858
        case 0x0b:/*MOVN*/ if(r[rt]) r[rd]=r[rs];    break;  /*IV*/
859 147 ja_rd
        case 0x0c:/*SYSCALL*/ trap_cause = 8;
860
                              s->exceptionId=1;
861 105 ja_rd
                              /*
862
                              FIXME enable when running uClinux
863
                              printf("SYSCALL (%08x)\n", s->pc);
864
                              */
865
                              break;
866 147 ja_rd
        case 0x0d:/*BREAK*/   trap_cause = 9;
867
                              s->exceptionId=1;
868 105 ja_rd
                              /*
869
                              FIXME enable when running uClinux
870
                              printf("BREAK (%08x)\n", s->pc);
871
                              */
872
                              break;
873 31 ja_rd
        case 0x0f:/*SYNC*/ s->wakeup=1;              break;
874
        case 0x10:/*MFHI*/ r[rd]=s->hi;              break;
875
        case 0x11:/*FTHI*/ s->hi=r[rs];              break;
876
        case 0x12:/*MFLO*/ r[rd]=s->lo;              break;
877
        case 0x13:/*MTLO*/ s->lo=r[rs];              break;
878
        case 0x18:/*MULT*/ mult_big_signed(r[rs],r[rt],&s->hi,&s->lo); break;
879
        case 0x19:/*MULTU*/ mult_big(r[rs],r[rt],&s->hi,&s->lo); break;
880
        case 0x1a:/*DIV*/  s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; break;
881
        case 0x1b:/*DIVU*/ s->lo=u[rs]/u[rt]; s->hi=u[rs]%u[rt]; break;
882
        case 0x20:/*ADD*/  r[rd]=r[rs]+r[rt];        break;
883
        case 0x21:/*ADDU*/ r[rd]=r[rs]+r[rt];        break;
884
        case 0x22:/*SUB*/  r[rd]=r[rs]-r[rt];        break;
885
        case 0x23:/*SUBU*/ r[rd]=r[rs]-r[rt];        break;
886
        case 0x24:/*AND*/  r[rd]=r[rs]&r[rt];        break;
887
        case 0x25:/*OR*/   r[rd]=r[rs]|r[rt];        break;
888
        case 0x26:/*XOR*/  r[rd]=r[rs]^r[rt];        break;
889
        case 0x27:/*NOR*/  r[rd]=~(r[rs]|r[rt]);     break;
890
        case 0x2a:/*SLT*/  r[rd]=r[rs]<r[rt];        break;
891
        case 0x2b:/*SLTU*/ r[rd]=u[rs]<u[rt];        break;
892
        case 0x2d:/*DADDU*/r[rd]=r[rs]+u[rt];        break;
893
        case 0x31:/*TGEU*/ break;
894
        case 0x32:/*TLT*/  break;
895
        case 0x33:/*TLTU*/ break;
896
        case 0x34:/*TEQ*/  break;
897
        case 0x36:/*TNE*/  break;
898 152 ja_rd
        default: printf("ERROR0(*0x%x~0x%x)\n", s->pc, opcode);
899
            /* FIXME should trap unknown opcode */
900
            s->wakeup=1;
901 31 ja_rd
        }
902
        break;
903
    case 0x01:/*REGIMM*/
904
        switch(rt){
905 2 ja_rd
            case 0x10:/*BLTZAL*/ r[31]=s->pc_next;
906
            case 0x00:/*BLTZ*/   branch=r[rs]<0;    break;
907
            case 0x11:/*BGEZAL*/ r[31]=s->pc_next;
908
            case 0x01:/*BGEZ*/   branch=r[rs]>=0;   break;
909
            case 0x12:/*BLTZALL*/r[31]=s->pc_next;
910
            case 0x02:/*BLTZL*/  lbranch=r[rs]<0;   break;
911
            case 0x13:/*BGEZALL*/r[31]=s->pc_next;
912
            case 0x03:/*BGEZL*/  lbranch=r[rs]>=0;  break;
913
            default: printf("ERROR1\n"); s->wakeup=1;
914 31 ja_rd
        }
915
        break;
916
    case 0x03:/*JAL*/    r[31]=s->pc_next;
917
    case 0x02:/*J*/      delay_slot=1;
918
                       s->pc_next=(s->pc&0xf0000000)|target; break;
919
    case 0x04:/*BEQ*/    branch=r[rs]==r[rt];     break;
920
    case 0x05:/*BNE*/    branch=r[rs]!=r[rt];     break;
921
    case 0x06:/*BLEZ*/   branch=r[rs]<=0;         break;
922
    case 0x07:/*BGTZ*/   branch=r[rs]>0;          break;
923
    case 0x08:/*ADDI*/   r[rt]=r[rs]+(short)imm;  break;
924
    case 0x09:/*ADDIU*/  u[rt]=u[rs]+(short)imm;  break;
925
    case 0x0a:/*SLTI*/   r[rt]=r[rs]<(short)imm;  break;
926
    case 0x0b:/*SLTIU*/  u[rt]=u[rs]<(unsigned int)(short)imm; break;
927
    case 0x0c:/*ANDI*/   r[rt]=r[rs]&imm;         break;
928
    case 0x0d:/*ORI*/    r[rt]=r[rs]|imm;         break;
929
    case 0x0e:/*XORI*/   r[rt]=r[rs]^imm;         break;
930
    case 0x0f:/*LUI*/    r[rt]=(imm<<16);         break;
931 152 ja_rd
    case 0x10:/*COP0*/
932
        if(s->status & 0x02){ /* kernel mode? */
933
            if((opcode & (1<<23)) == 0){  //move from CP0 (mfc0)
934
                switch(rd){
935
                    case 12: r[rt]=s->status & 0x0000003f; break;
936
                    case 13: r[rt]=s->cp0_cause; break;
937
                    case 14: r[rt]=s->epc; break;
938
                    case 15: r[rt]=R3000_ID; break;
939
                    default:
940
                        //printf("mfco [%02d]\n", rd);
941
                        break;
942
                }
943 27 ja_rd
            }
944 152 ja_rd
            else{                         //move to CP0 (mtc0)
945
                /* FIXME check CF= reg address */
946
                s->status=r[rt] & 0x0003003f; /* mask W/O bits */
947
                if(s->processId && (r[rt]&2)){
948
                    s->userMode|=r[rt]&2;
949
                    //printf("CpuStatus=%d %d %d\n", r[rt], s->status, s->userMode);
950
                    //s->wakeup = 1;
951
                    //printf("pc=0x%x\n", epc);
952
                }
953
            }
954
        }
955
        else{
956
            /* tried to execute mtc* or mfc* in user mode: trap */
957
            trap_cause = 11; /* unavailable coprocessor */
958
            s->exceptionId=1;
959 31 ja_rd
        }
960
        break;
961 105 ja_rd
    case 0x11:/*COP1*/  unimplemented(s,"COP1");
962
                        break;
963 2 ja_rd
//      case 0x12:/*COP2*/ break;
964
//      case 0x13:/*COP3*/ break;
965 31 ja_rd
    case 0x14:/*BEQL*/  lbranch=r[rs]==r[rt];    break;
966
    case 0x15:/*BNEL*/  lbranch=r[rs]!=r[rt];    break;
967
    case 0x16:/*BLEZL*/ lbranch=r[rs]<=0;        break;
968
    case 0x17:/*BGTZL*/ lbranch=r[rs]>0;         break;
969 2 ja_rd
//      case 0x1c:/*MAD*/  break;   /*IV*/
970 31 ja_rd
    case 0x20:/*LB*/    //r[rt]=(signed char)mem_read(s,1,ptr,1);  break;
971 53 ja_rd
                        start_load(s, ptr, rt,(signed char)mem_read(s,1,ptr,1));
972 31 ja_rd
                        break;
973 2 ja_rd
 
974 31 ja_rd
    case 0x21:/*LH*/    //r[rt]=(signed short)mem_read(s,2,ptr,1); break;
975 53 ja_rd
                        start_load(s, ptr, rt, (signed short)mem_read(s,2,ptr,1));
976 31 ja_rd
                        break;
977 105 ja_rd
    case 0x22:/*LWL*/   mem_lwl(s, ptr, rt, 1);
978
                        //printf("LWL\n");
979 31 ja_rd
                        break;
980
    case 0x23:/*LW*/    //r[rt]=mem_read(s,4,ptr,1);   break;
981 53 ja_rd
                        start_load(s, ptr, rt, mem_read(s,4,ptr,1));
982 31 ja_rd
                        break;
983
    case 0x24:/*LBU*/   //r[rt]=(unsigned char)mem_read(s,1,ptr,1); break;
984 53 ja_rd
                        start_load(s, ptr, rt, (unsigned char)mem_read(s,1,ptr,1));
985 31 ja_rd
                        break;
986
    case 0x25:/*LHU*/   //r[rt]= (unsigned short)mem_read(s,2,ptr,1);
987 53 ja_rd
                        start_load(s, ptr, rt, (unsigned short)mem_read(s,2,ptr,1));
988 31 ja_rd
                        break;
989 105 ja_rd
    case 0x26:/*LWR*/   mem_lwr(s, ptr, rt, 1);
990
                        //printf("LWR\n");
991 31 ja_rd
                        break;
992
    case 0x28:/*SB*/    mem_write(s,1,ptr,r[rt],1);  break;
993
    case 0x29:/*SH*/    mem_write(s,2,ptr,r[rt],1);  break;
994 105 ja_rd
    case 0x2a:/*SWL*/   mem_swl(s, ptr, r[rt], 1);
995
                        //printf("SWL\n");
996
                        break;
997 31 ja_rd
    case 0x2b:/*SW*/    mem_write(s,4,ptr,r[rt],1);  break;
998 105 ja_rd
    case 0x2e:/*SWR*/   mem_swr(s, ptr, r[rt], 1);
999
                        //printf("SWR\n");
1000
                        break;
1001
    case 0x2f:/*CACHE*/ unimplemented(s,"CACHE");
1002
                        break;
1003
    case 0x30:/*LL*/    //unimplemented(s,"LL");
1004 53 ja_rd
                        start_load(s, ptr, rt, mem_read(s,4,ptr,1));
1005 31 ja_rd
                        break;
1006 2 ja_rd
//      case 0x31:/*LWC1*/ break;
1007
//      case 0x32:/*LWC2*/ break;
1008
//      case 0x33:/*LWC3*/ break;
1009
//      case 0x35:/*LDC1*/ break;
1010
//      case 0x36:/*LDC2*/ break;
1011
//      case 0x37:/*LDC3*/ break;
1012
//      case 0x38:/*SC*/     *(int*)ptr=r[rt]; r[rt]=1; break;
1013 31 ja_rd
    case 0x38:/*SC*/    mem_write(s,4,ptr,r[rt],1); r[rt]=1; break;
1014 2 ja_rd
//      case 0x39:/*SWC1*/ break;
1015
//      case 0x3a:/*SWC2*/ break;
1016
//      case 0x3b:/*SWC3*/ break;
1017
//      case 0x3d:/*SDC1*/ break;
1018
//      case 0x3e:/*SDC2*/ break;
1019
//      case 0x3f:/*SDC3*/ break;
1020 31 ja_rd
    default:
1021 147 ja_rd
        ;
1022 31 ja_rd
        /* FIXME should trap unimplemented opcodes */
1023 147 ja_rd
        /* FIXME newlib */
1024 152 ja_rd
        printf("ERROR2 address=0x%x opcode=0x%x -- ", epc, opcode);
1025
        print_opcode_fields(opcode);
1026
        printf("\n");
1027 31 ja_rd
        s->wakeup=1;
1028
    }
1029 53 ja_rd
 
1030
    /* adjust next PC if this was a ajump instruction */
1031 31 ja_rd
    s->pc_next += (branch || lbranch == 1) ? imm_shift : 0;
1032
    s->pc_next &= ~3;
1033
    s->skip = (lbranch == 0) | skip2;
1034 2 ja_rd
 
1035 31 ja_rd
    /* If there was trouble (failed assertions), log it */
1036
    if(s->failed_assertions!=0){
1037
        log_failed_assertions(s);
1038
        s->failed_assertions=0;
1039
    }
1040 5 ja_rd
 
1041 31 ja_rd
    /* if there's a delayed load pending, do it now: load reg with memory data*/
1042
    /* load delay slots not simulated */
1043 2 ja_rd
 
1044 31 ja_rd
    /* Handle exceptions */
1045
   if(s->exceptionId){
1046
        r[rt] = rSave;
1047 152 ja_rd
        /* set cause field ... */
1048
        s->cp0_cause = (s->delay_slot & 0x1) << 31 | (trap_cause & 0x1f) << 2;
1049
        /* ...save previous KU/IE flags in SR... */
1050
        s->status = (s->status & 0xffffffc3) | ((s->status & 0x0f) << 2);
1051
        /* ...and raise KU(EXL) kernel mode flag */
1052
        s->status |= 0x02;
1053 31 ja_rd
        /* adjust epc if we (i.e. the victim instruction) are in a delay slot */
1054
        if(s->delay_slot){
1055 152 ja_rd
            epc = epc - 4;
1056 31 ja_rd
        }
1057
        s->epc = epc;
1058 61 ja_rd
        s->pc_next = VECTOR_TRAP;
1059 31 ja_rd
        s->skip = 1;
1060
        s->exceptionId = 0;
1061
        s->userMode = 0;
1062
        //s->wakeup = 1;
1063
    }
1064 27 ja_rd
 
1065 53 ja_rd
    /* if we're NOT showing output to console, log state of CPU to file */
1066
    if(!show_mode){
1067
        log_cycle(s);
1068
    }
1069
 
1070
 
1071
 
1072 31 ja_rd
    /* if this instruction was any kind of branch that actually jumped, then
1073
       the next instruction will be in a delay slot. Remember it. */
1074
    delay_slot = ((lbranch==1) || branch || delay_slot);
1075
    s->delay_slot = delay_slot;
1076 2 ja_rd
}
1077
 
1078 152 ja_rd
/** Print opcode fields for easier debugging */
1079
void print_opcode_fields(uint32_t opcode){
1080
    uint32_t field;
1081
 
1082
    field = (opcode >> 26)&0x3f;
1083
    printf("%02x:", field);
1084
    field = (opcode >> 21)&0x1f;
1085
    printf("%02x:", field);
1086
    field = (opcode >> 16)&0x1f;
1087
    printf("%02x:", field);
1088
    field = (opcode >> 11)&0x1f;
1089
    printf("%02x:", field);
1090
    field = (opcode >>  6)&0x1f;
1091
    printf("%02x:", field);
1092
    field = (opcode >>  0)&0x3f;
1093
    printf("%02x",  field);
1094
}
1095
 
1096
 
1097 2 ja_rd
/** Dump CPU state to console */
1098 31 ja_rd
void show_state(t_state *s){
1099
    int i,j;
1100
    printf("pid=%d userMode=%d, epc=0x%x\n", s->processId, s->userMode, s->epc);
1101
    printf("hi=0x%08x lo=0x%08x\n", s->hi, s->lo);
1102
    for(i = 0; i < 4; ++i){
1103
        printf("%2.2d ", i * 8);
1104
        for(j = 0; j < 8; ++j){
1105
            printf("%8.8x ", s->r[i*8+j]);
1106
        }
1107
        printf("\n");
1108
    }
1109
    //printf("%8.8lx %8.8lx %8.8lx %8.8lx\n", s->pc, s->pc_next, s->hi, s->lo);
1110
    j = s->pc;
1111
    for(i = -4; i <= 8; ++i){
1112
        printf("%c", i==0 ? '*' : ' ');
1113
        s->pc = j + i * 4;
1114
        cycle(s, 10);
1115
    }
1116
    s->pc = j;
1117 2 ja_rd
}
1118
 
1119
/** Show debug monitor prompt and execute user command */
1120 105 ja_rd
void do_debug(t_state *s, uint32_t no_prompt){
1121 31 ja_rd
    int ch;
1122 105 ja_rd
    int i, j=0, watch=0, addr;
1123
    j = s->breakpoint;
1124 31 ja_rd
    s->pc_next = s->pc + 4;
1125
    s->skip = 0;
1126 105 ja_rd
    s->wakeup = 0;
1127
 
1128
    printf("Starting simulation.\n");
1129
 
1130
    if(no_prompt){
1131
        ch = '5'; /* 'go' command */
1132
        printf("\n\n");
1133
    }
1134
    else{
1135
        show_state(s);
1136
        ch = ' ';
1137
    }
1138
 
1139 31 ja_rd
    for(;;){
1140 105 ja_rd
        if(ch != 'n' && !no_prompt){
1141 31 ja_rd
            if(watch){
1142
                printf("0x%8.8x=0x%8.8x\n", watch, mem_read(s, 4, watch,0));
1143 2 ja_rd
            }
1144 31 ja_rd
            printf("1=Debug 2=t_trace 3=Step 4=BreakPt 5=Go 6=Memory ");
1145 93 ja_rd
            printf("7=Watch 8=Jump 9=Quit A=Dump\n");
1146
            printf("L=LogTrigger > ");
1147 31 ja_rd
        }
1148 105 ja_rd
        if(ch==' ') ch = getch();
1149 31 ja_rd
        if(ch != 'n'){
1150
            printf("\n");
1151
        }
1152
        switch(ch){
1153
        case 'a': case 'A':
1154
            dump_trace_buffer(s); break;
1155
        case '1': case 'd': case ' ':
1156
            cycle(s, 0); show_state(s); break;
1157
        case 'n':
1158
            cycle(s, 1); break;
1159
        case '2': case 't':
1160
            cycle(s, 0); printf("*"); cycle(s, 10); break;
1161
        case '3': case 's':
1162
            printf("Count> ");
1163
            scanf("%d", &j);
1164
            for(i = 0; i < j; ++i){
1165
                cycle(s, 1);
1166
            }
1167
            show_state(s);
1168
            break;
1169
        case '4': case 'b':
1170
            printf("Line> ");
1171
            scanf("%x", &j);
1172
            printf("break point=0x%x\n", j);
1173
            break;
1174
        case '5': case 'g':
1175
            s->wakeup = 0;
1176 2 ja_rd
            cycle(s, 0);
1177 31 ja_rd
            while(s->wakeup == 0){
1178
                if(s->pc == j){
1179
                    printf("\n\nStop: pc = 0x%08x\n\n", j);
1180
                    break;
1181
                }
1182
                cycle(s, 0);
1183 105 ja_rd
            }
1184
            if(no_prompt) return;
1185 31 ja_rd
            show_state(s);
1186
            break;
1187
        case 'G':
1188
            s->wakeup = 0;
1189 2 ja_rd
            cycle(s, 1);
1190 31 ja_rd
            while(s->wakeup == 0){
1191
                if(s->pc == j){
1192
                    break;
1193
                }
1194
                cycle(s, 1);
1195
            }
1196
            show_state(s);
1197
            break;
1198
        case '6': case 'm':
1199
            printf("Memory> ");
1200
            scanf("%x", &j);
1201
            for(i = 0; i < 8; ++i){
1202
                printf("%8.8x ", mem_read(s, 4, j+i*4, 0));
1203
            }
1204
            printf("\n");
1205
            break;
1206
        case '7': case 'w':
1207
            printf("Watch> ");
1208
            scanf("%x", &watch);
1209
            break;
1210
        case '8': case 'j':
1211
            printf("Jump> ");
1212
            scanf("%x", &addr);
1213
            s->pc = addr;
1214
            s->pc_next = addr + 4;
1215
            show_state(s);
1216 93 ja_rd
            break;
1217
        case '9': case 'q':
1218
            return;
1219
        case 'l':
1220
            printf("Address> ");
1221
            scanf("%x", &(s->t.log_trigger_address));
1222
            printf("Log trigger address=0x%x\n", s->t.log_trigger_address);
1223 31 ja_rd
            break;
1224 105 ja_rd
        }
1225
        ch = ' ';
1226 31 ja_rd
    }
1227 2 ja_rd
}
1228
 
1229
/** Read binary code and data files */
1230 61 ja_rd
int read_binary_files(t_state *s, t_args *args){
1231 31 ja_rd
    FILE *in;
1232 105 ja_rd
    uint8_t *target;
1233
    uint32_t bytes=0, i, files_read=0;
1234 2 ja_rd
 
1235 31 ja_rd
    for(i=0;i<NUM_MEM_BLOCKS;i++){
1236 105 ja_rd
        bytes = 0;
1237 61 ja_rd
        if(args->bin_filename[i]!=NULL){
1238
 
1239
            in = fopen(args->bin_filename[i], "rb");
1240 31 ja_rd
            if(in == NULL){
1241 44 ja_rd
                free_cpu(s);
1242 61 ja_rd
                printf("Can't open file %s, quitting!\n",args->bin_filename[i]);
1243
                return(0);
1244 31 ja_rd
            }
1245 2 ja_rd
 
1246 105 ja_rd
            /* FIXME load offset 0x2000 for linux kernel hardcoded! */
1247
            //bytes = fread((s->blocks[i].mem + 0x2000), 1, s->blocks[i].size, in);
1248
            target = (uint8_t *)(s->blocks[i].mem + args->offset[i]);
1249
            while(!feof(in) &&
1250
                  ((bytes+1024+args->offset[i]) < (s->blocks[i].size))){
1251
                bytes += fread(&(target[bytes]), 1, 1024, in);
1252
                if(errno!=0){
1253
                    printf("ERROR: file load failed with code %d ('%s')\n",
1254
                        errno, strerror(errno));
1255
                    free_cpu(s);
1256
                    return 0;
1257
                }
1258
            }
1259
 
1260 31 ja_rd
            fclose(in);
1261 105 ja_rd
 
1262
            /* Now reverse the endianness of the data we just read, if it's
1263
             necessary. */
1264
             /* FIXME add cmd line param, etc. */
1265
            //reverse_endianess(target, bytes);
1266
 
1267 31 ja_rd
            files_read++;
1268
        }
1269 105 ja_rd
        printf("%-16s [size= %6dKB, start= 0x%08x] loaded %d bytes.\n",
1270
                s->blocks[i].area_name,
1271
                s->blocks[i].size/1024,
1272
                s->blocks[i].start,
1273
                bytes);
1274 31 ja_rd
    }
1275
 
1276
    if(!files_read){
1277 44 ja_rd
        free_cpu(s);
1278 31 ja_rd
        printf("No binary object files read, quitting\n");
1279 44 ja_rd
        return 0;
1280 31 ja_rd
    }
1281
 
1282 44 ja_rd
    return files_read;
1283 2 ja_rd
}
1284 105 ja_rd
 
1285
void reverse_endianess(uint8_t *data, uint32_t bytes){
1286
    uint8_t w[4];
1287
    uint32_t i, j;
1288
 
1289
    for(i=0;i<bytes;i=i+4){
1290
        for(j=0;j<4;j++){
1291
            w[3-j] = data[i+j];
1292
        }
1293
        for(j=0;j<4;j++){
1294
            data[i+j] = w[j];
1295
        }
1296
    }
1297
}
1298
 
1299 2 ja_rd
 
1300
/*----------------------------------------------------------------------------*/
1301
 
1302 31 ja_rd
int main(int argc,char *argv[]){
1303
    t_state state, *s=&state;
1304 105 ja_rd
 
1305
    /* Parse command line and pass any relevant arguments to CPU record */
1306
    if(parse_cmd_line(argc,argv, &cmd_line_args)==0){
1307
        return 0;
1308
    }
1309 2 ja_rd
 
1310 61 ja_rd
    printf("MIPS-I emulator (" __DATE__ ")\n\n");
1311 105 ja_rd
    if(!init_cpu(s, &cmd_line_args)){
1312 44 ja_rd
        printf("Trouble allocating memory, quitting!\n");
1313
        return 1;
1314
    };
1315 61 ja_rd
 
1316 93 ja_rd
    /* Read binary object files into memory*/
1317 61 ja_rd
    if(!read_binary_files(s, &cmd_line_args)){
1318 31 ja_rd
        return 2;
1319
    }
1320 61 ja_rd
    printf("\n\n");
1321 2 ja_rd
 
1322 93 ja_rd
    init_trace_buffer(s, &cmd_line_args);
1323 2 ja_rd
 
1324 31 ja_rd
    /* NOTE: Original mlite supported loading little-endian code, which this
1325 2 ja_rd
      program doesn't. The endianess-conversion code has been removed.
1326 31 ja_rd
    */
1327 2 ja_rd
 
1328 31 ja_rd
    /* Simulate a CPU reset */
1329 105 ja_rd
    reset_cpu(s);
1330
 
1331
    /* Simulate the work of the uClinux bootloader */
1332
    if(cmd_line_args.memory_map == MAP_UCLINUX){
1333
        /* FIXME this is a stub, flesh it out */
1334
        s->pc = 0x80002400;
1335
    }
1336 2 ja_rd
 
1337 31 ja_rd
    /* Enter debug command interface; will only exit clean with user command */
1338 105 ja_rd
    do_debug(s, cmd_line_args.no_prompt);
1339 2 ja_rd
 
1340 31 ja_rd
    /* Close and deallocate everything and quit */
1341
    close_trace_buffer(s);
1342
    free_cpu(s);
1343
    return(0);
1344 2 ja_rd
}
1345
 
1346
/*----------------------------------------------------------------------------*/
1347
 
1348
 
1349 93 ja_rd
void init_trace_buffer(t_state *s, t_args *args){
1350 31 ja_rd
    int i;
1351 2 ja_rd
 
1352
#if FILE_LOGGING_DISABLED
1353 31 ja_rd
    s->t.log = NULL;
1354 93 ja_rd
    s->t.log_triggered = 0;
1355 31 ja_rd
    return;
1356 2 ja_rd
#else
1357 93 ja_rd
    /* clear trace buffer */
1358 31 ja_rd
    for(i=0;i<TRACE_BUFFER_SIZE;i++){
1359
        s->t.buf[i]=0xffffffff;
1360
    }
1361
    s->t.next = 0;
1362 2 ja_rd
 
1363 31 ja_rd
    /* if file logging is enabled, open log file */
1364 93 ja_rd
    if(args->log_file_name!=NULL){
1365
        s->t.log = fopen(args->log_file_name, "w");
1366 31 ja_rd
        if(s->t.log==NULL){
1367
            printf("Error opening log file '%s', file logging disabled\n",
1368 93 ja_rd
                    args->log_file_name);
1369 31 ja_rd
        }
1370
    }
1371
    else{
1372
        s->t.log = NULL;
1373
    }
1374 93 ja_rd
 
1375
    /* Setup log trigger */
1376
    s->t.log_triggered = 0;
1377
    s->t.log_trigger_address = args->log_trigger_address;
1378 2 ja_rd
#endif
1379
}
1380
 
1381
/** Dumps last jump targets as a chunk of hex numbers (older is left top) */
1382 31 ja_rd
void dump_trace_buffer(t_state *s){
1383
    int i, col;
1384 2 ja_rd
 
1385 31 ja_rd
    for(i=0, col=0;i<TRACE_BUFFER_SIZE;i++, col++){
1386
        printf("%08x ", s->t.buf[s->t.next + i]);
1387
        if((col % 8)==7){
1388
            printf("\n");
1389
        }
1390
    }
1391 2 ja_rd
}
1392
 
1393
/** Logs last cycle's activity (changes in state and/or loads/stores) */
1394 31 ja_rd
void log_cycle(t_state *s){
1395
    static unsigned int last_pc = 0;
1396
    int i;
1397 53 ja_rd
    uint32_t log_pc;
1398 2 ja_rd
 
1399 31 ja_rd
    /* store PC in trace buffer only if there was a jump */
1400
    if(s->pc != (last_pc+4)){
1401
        s->t.buf[s->t.next] = s->pc;
1402
        s->t.next = (s->t.next + 1) % TRACE_BUFFER_SIZE;
1403
    }
1404
    last_pc = s->pc;
1405 2 ja_rd
 
1406 31 ja_rd
    /* if file logging is enabled, dump a trace log to file */
1407 93 ja_rd
    if(log_enabled(s)){
1408 53 ja_rd
        log_pc = s->op_addr;
1409
 
1410 147 ja_rd
        /* skip register zero which does not change */
1411
        for(i=1;i<32;i++){
1412 31 ja_rd
            if(s->t.pr[i] != s->r[i]){
1413 53 ja_rd
                fprintf(s->t.log, "(%08X) [%02X]=%08X\n", log_pc, i, s->r[i]);
1414 31 ja_rd
            }
1415
            s->t.pr[i] = s->r[i];
1416
        }
1417
        if(s->lo != s->t.lo){
1418 147 ja_rd
            //fprintf(s->t.log, "(%08X) [LO]=%08X\n", log_pc, s->lo);
1419 31 ja_rd
        }
1420
        s->t.lo = s->lo;
1421 2 ja_rd
 
1422 31 ja_rd
        if(s->hi != s->t.hi){
1423 147 ja_rd
            //fprintf(s->t.log, "(%08X) [HI]=%08X\n", log_pc, s->hi);
1424 31 ja_rd
        }
1425
        s->t.hi = s->hi;
1426 2 ja_rd
 
1427 152 ja_rd
        /* Catch changes in EPC by direct write (mtc0) and by exception */
1428 31 ja_rd
        if(s->epc != s->t.epc){
1429 53 ja_rd
            fprintf(s->t.log, "(%08X) [EP]=%08X\n", log_pc, s->epc);
1430 31 ja_rd
        }
1431
        s->t.epc = s->epc;
1432 152 ja_rd
 
1433
        if(s->status != s->t. status){
1434
            fprintf(s->t.log, "(%08X) [SR]=%08X\n", log_pc, s->status);
1435
        }
1436
        s->t.status = s->status;
1437 31 ja_rd
    }
1438 2 ja_rd
}
1439
 
1440
/** Frees debug buffers and closes log file */
1441 31 ja_rd
void close_trace_buffer(t_state *s){
1442
    if(s->t.log){
1443
        fclose(s->t.log);
1444
    }
1445 2 ja_rd
}
1446 5 ja_rd
 
1447
/** Logs a message for each failed assertion, each in a line */
1448 31 ja_rd
void log_failed_assertions(t_state *s){
1449
    unsigned bitmap = s->failed_assertions;
1450
    int i = 0;
1451 5 ja_rd
 
1452 31 ja_rd
    /* This loop will crash the program if the message table is too short...*/
1453
    if(s->t.log != NULL){
1454
        for(i=0;i<32;i++){
1455
            if(bitmap & 0x1){
1456
                fprintf(s->t.log, "ASSERTION FAILED: [%08x] %s\n",
1457
                        s->faulty_address,
1458
                        assertion_messages[i]);
1459
            }
1460
            bitmap = bitmap >> 1;
1461
        }
1462
    }
1463 5 ja_rd
}
1464 31 ja_rd
 
1465 93 ja_rd
uint32_t log_enabled(t_state *s){
1466
    return ((s->t.log != NULL) && (s->t.log_triggered!=0));
1467
}
1468
 
1469
void trigger_log(t_state *s){
1470
    uint32_t i;
1471
 
1472
    s->t.log_triggered = 1;
1473
 
1474
    for(i=0;i<32;i++){
1475
        s->t.pr[i] = s->r[i];
1476
    }
1477
 
1478
    s->t.lo = s->lo;
1479
    s->t.hi = s->hi;
1480
    s->t.epc = s->epc;
1481
}
1482
 
1483 31 ja_rd
void free_cpu(t_state *s){
1484
    int i;
1485
 
1486
    for(i=0;i<NUM_MEM_BLOCKS;i++){
1487
        free(s->blocks[i].mem);
1488
        s->blocks[i].mem = NULL;
1489
    }
1490
}
1491
 
1492
void reset_cpu(t_state *s){
1493
    s->pc = VECTOR_RESET;     /* reset start vector */
1494
    s->delay_slot = 0;
1495
    s->failed_assertions = 0; /* no failed assertions pending */
1496 152 ja_rd
    s->status = 0x02; /* kernel mode, interrupts disabled */
1497
    /* init trace struct to prevent spurious logs */
1498
    s->t.status = s->status;
1499 31 ja_rd
}
1500 105 ja_rd
 
1501
void unimplemented(t_state *s, const char *txt){
1502
    /* FIXME unimplemented opcode trap */
1503
    printf("UNIMPLEMENTED: %s\n", txt);
1504
}
1505 31 ja_rd
 
1506 105 ja_rd
int init_cpu(t_state *s, t_args *args){
1507
    int i, j;
1508
    uint32_t k = args->memory_map;
1509 44 ja_rd
 
1510 31 ja_rd
    memset(s, 0, sizeof(t_state));
1511
    s->big_endian = 1;
1512 61 ja_rd
 
1513 105 ja_rd
    s->do_unaligned = args->do_unaligned;
1514
    s->breakpoint = args->breakpoint;
1515
 
1516 61 ja_rd
    /* Initialize memory map */
1517 31 ja_rd
    for(i=0;i<NUM_MEM_BLOCKS;i++){
1518 105 ja_rd
        s->blocks[i].start =        memory_maps[k].blocks[i].start;
1519
        s->blocks[i].size =         memory_maps[k].blocks[i].size;
1520
        s->blocks[i].area_name =    memory_maps[k].blocks[i].area_name;
1521
        s->blocks[i].mask =         memory_maps[k].blocks[i].mask;
1522
        s->blocks[i].read_only =    memory_maps[k].blocks[i].read_only;
1523 44 ja_rd
 
1524
        s->blocks[i].mem = (unsigned char*)malloc(s->blocks[i].size);
1525
 
1526
        if(s->blocks[i].mem == NULL){
1527
            for(j=0;j<i;j++){
1528
                free(s->blocks[j].mem);
1529
            }
1530
            return 0;
1531
        }
1532
        memset(s->blocks[i].mem, 0, s->blocks[i].size);
1533 105 ja_rd
    }
1534 44 ja_rd
    return NUM_MEM_BLOCKS;
1535 31 ja_rd
}
1536 61 ja_rd
 
1537
int32_t parse_cmd_line(uint32_t argc, char **argv, t_args *args){
1538
    uint32_t i;
1539
 
1540 105 ja_rd
    /* fill cmd line args with default values */
1541
    args->memory_map = MAP_DEFAULT;
1542
    args->do_unaligned = 0;
1543
    args->no_prompt = 0;
1544
    args->breakpoint = 0xffffffff;
1545
    args->log_file_name = "sw_sim_log.txt";
1546
    args->log_trigger_address = VECTOR_RESET;
1547 61 ja_rd
    for(i=0;i<NUM_MEM_BLOCKS;i++){
1548
        args->bin_filename[i] = NULL;
1549 105 ja_rd
        args->offset[i] = 0;
1550 61 ja_rd
    }
1551
 
1552
    /* parse actual cmd line args */
1553
    for(i=1;i<argc;i++){
1554
        if(strcmp(argv[i],"--plasma")==0){
1555 105 ja_rd
            /* plasma simulation not supported, error*/
1556
            printf("Error: program compiled for compatibility to MIPS-I\n");
1557
            return 0;
1558
        }
1559
        else if(strcmp(argv[i],"--uclinux")==0){
1560
            args->memory_map = MAP_UCLINUX;
1561
            /* FIXME selecting uClinux enables unaligned L/S emulation */
1562
            args->do_unaligned = 1;
1563 61 ja_rd
        }
1564 108 ja_rd
        else if(strcmp(argv[i],"--small")==0){
1565
            args->memory_map = MAP_SMALL;
1566
        }
1567 105 ja_rd
        else if(strcmp(argv[i],"--unaligned")==0){
1568
            args->do_unaligned = 1;
1569
        }
1570
        else if(strcmp(argv[i],"--noprompt")==0){
1571
            args->no_prompt = 1;
1572
        }
1573 61 ja_rd
        else if(strncmp(argv[i],"--bram=", strlen("--bram="))==0){
1574
            args->bin_filename[0] = &(argv[i][strlen("--bram=")]);
1575
        }
1576
        else if(strncmp(argv[i],"--flash=", strlen("--flash="))==0){
1577 105 ja_rd
            args->bin_filename[3] = &(argv[i][strlen("--flash=")]);
1578 61 ja_rd
        }
1579
        else if(strncmp(argv[i],"--xram=", strlen("--xram="))==0){
1580
            args->bin_filename[1] = &(argv[i][strlen("--xram=")]);
1581
        }
1582 105 ja_rd
        else if(strncmp(argv[i],"--kernel=", strlen("--kernel="))==0){
1583
            args->bin_filename[1] = &(argv[i][strlen("--kernel=")]);
1584
            /* FIXME uClinux kernel 'offset' hardcoded */
1585
            args->offset[1] = 0x2000;
1586
        }
1587 93 ja_rd
        else if(strncmp(argv[i],"--trigger=", strlen("--trigger="))==0){
1588
            sscanf(&(argv[i][strlen("--trigger=")]), "%x", &(args->log_trigger_address));
1589
        }
1590 105 ja_rd
        else if(strncmp(argv[i],"--breakpoint=", strlen("--breakpoint="))==0){
1591
            sscanf(&(argv[i][strlen("--breakpoint=")]), "%x", &(args->breakpoint));
1592
        }
1593 61 ja_rd
        else if((strcmp(argv[i],"--help")==0)||(strcmp(argv[i],"-h")==0)){
1594
            usage();
1595
            return 0;
1596
        }
1597
        else{
1598
            printf("unknown argument '%s'\n\n",argv[i]);
1599
            usage();
1600
            return 0;
1601
        }
1602
    }
1603
 
1604
    return 1;
1605
}
1606
 
1607
void usage(void){
1608
    printf("Usage:");
1609
    printf("    slite file.exe [arguments]\n");
1610
    printf("Arguments:\n");
1611
    printf("--bram=<file name>      : BRAM initialization file\n");
1612
    printf("--xram=<file name>      : XRAM initialization file\n");
1613 105 ja_rd
    printf("--kernel=<file name>    : XRAM initialization file for uClinux kernel\n");
1614
    printf("                          (loads at block offset 0x2000)\n");
1615 61 ja_rd
    printf("--flash=<file name>     : FLASH initialization file\n");
1616 93 ja_rd
    printf("--trigger=<hex number>  : Log trigger address\n");
1617 61 ja_rd
    printf("--plasma                : Simulate Plasma instead of MIPS-I\n");
1618 105 ja_rd
    printf("--uclinux               : Use memory map tailored to uClinux\n");
1619
    printf("--unaligned             : Implement unaligned load/store instructions\n");
1620
    printf("--noprompt              : Run in batch mode\n");
1621
    printf("--stop_at_zero          : Stop simulation when fetching from address 0x0\n");
1622 61 ja_rd
    printf("--help, -h              : Show this usage text\n");
1623
}
1624 105 ja_rd
 

powered by: WebSVN 2.1.0

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