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

Subversion Repositories ion

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

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

powered by: WebSVN 2.1.0

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