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

Subversion Repositories ion

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

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

powered by: WebSVN 2.1.0

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