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

Subversion Repositories ion

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

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

powered by: WebSVN 2.1.0

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