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

Subversion Repositories ion

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

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

powered by: WebSVN 2.1.0

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