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

Subversion Repositories ion

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

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

powered by: WebSVN 2.1.0

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