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

Subversion Repositories ion

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

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

powered by: WebSVN 2.1.0

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