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

Subversion Repositories mlite

[/] [mlite/] [trunk/] [tools/] [mlite.c] - Blame information for rev 241

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 41 rhoads
/*-------------------------------------------------------------------
2 43 rhoads
-- TITLE: Plasma CPU in software.  Executes MIPS(tm) opcodes.
3 41 rhoads
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4
-- DATE CREATED: 1/31/01
5
-- FILENAME: mlite.c
6 43 rhoads
-- PROJECT: Plasma CPU core
7 41 rhoads
-- COPYRIGHT: Software placed into the public domain by the author.
8
--    Software 'as is' without warranty.  Author liable for nothing.
9
-- DESCRIPTION:
10 43 rhoads
--   Plasma CPU simulator in C code.
11 41 rhoads
--   This file served as the starting point for the VHDL code.
12 194 rhoads
--   Assumes running on a little endian PC.
13 41 rhoads
--------------------------------------------------------------------*/
14
#include <stdio.h>
15
#include <stdlib.h>
16
#include <string.h>
17
#include <ctype.h>
18 137 rhoads
#include <assert.h>
19 41 rhoads
 
20 194 rhoads
//#define ENABLE_CACHE
21
 
22 41 rhoads
#define MEM_SIZE (1024*1024*2)
23
#define ntohs(A) ( ((A)>>8) | (((A)&0xff)<<8) )
24
#define htons(A) ntohs(A)
25
#define ntohl(A) ( ((A)>>24) | (((A)&0xff0000)>>8) | (((A)&0xff00)<<8) | ((A)<<24) )
26
#define htonl(A) ntohl(A)
27
 
28 137 rhoads
#ifndef WIN32
29 104 rhoads
#define getch getchar
30 137 rhoads
void Sleep(unsigned long value)
31
{
32
   volatile unsigned long count = value*1000000;
33
   while(--count > 0) ;
34
}
35
#else
36 194 rhoads
#include <conio.h>
37 137 rhoads
extern void __stdcall Sleep(unsigned long value);
38
#endif
39 41 rhoads
 
40 137 rhoads
#define UART_WRITE        0x20000000
41
#define UART_READ         0x20000000
42
#define IRQ_MASK          0x20000010
43
#define IRQ_STATUS        0x20000020
44 194 rhoads
#define CONFIG_REG        0x20000070
45
#define MMU_PROCESS_ID    0x20000080
46
#define MMU_FAULT_ADDR    0x20000090
47
#define MMU_TLB           0x200000a0
48 137 rhoads
 
49 194 rhoads
#define IRQ_UART_READ_AVAILABLE  0x001
50
#define IRQ_UART_WRITE_AVAILABLE 0x002
51
#define IRQ_COUNTER18_NOT        0x004
52
#define IRQ_COUNTER18            0x008
53
#define IRQ_MMU                  0x200
54 137 rhoads
 
55 194 rhoads
#define MMU_ENTRIES 4
56
#define MMU_MASK (1024*4-1)
57
typedef struct
58
{
59
   unsigned long virtualAddress;
60
   unsigned long physicalAddress;
61
} MmuEntry;
62
 
63 41 rhoads
typedef struct {
64
   long r[32];
65 194 rhoads
   long pc, pc_next, epc;
66
   unsigned long hi;
67
   unsigned long lo;
68
   long status;
69
   long userMode;
70
   long processId;
71
   long exceptionId;
72
   long faultAddr;
73
   long irqStatus;
74 41 rhoads
   long skip;
75 137 rhoads
   unsigned char *mem;
76 41 rhoads
   long wakeup;
77
   long big_endian;
78 194 rhoads
   MmuEntry mmuEntry[MMU_ENTRIES];
79 41 rhoads
} State;
80
 
81
static char *opcode_string[]={
82
   "SPECIAL","REGIMM","J","JAL","BEQ","BNE","BLEZ","BGTZ",
83
   "ADDI","ADDIU","SLTI","SLTIU","ANDI","ORI","XORI","LUI",
84
   "COP0","COP1","COP2","COP3","BEQL","BNEL","BLEZL","BGTZL",
85
   "?","?","?","?","?","?","?","?",
86
   "LB","LH","LWL","LW","LBU","LHU","LWR","?",
87
   "SB","SH","SWL","SW","?","?","SWR","CACHE",
88
   "LL","LWC1","LWC2","LWC3","?","LDC1","LDC2","LDC3"
89
   "SC","SWC1","SWC2","SWC3","?","SDC1","SDC2","SDC3"
90
};
91
 
92
static char *special_string[]={
93
   "SLL","?","SRL","SRA","SLLV","?","SRLV","SRAV",
94
   "JR","JALR","MOVZ","MOVN","SYSCALL","BREAK","?","SYNC",
95
   "MFHI","MTHI","MFLO","MTLO","?","?","?","?",
96
   "MULT","MULTU","DIV","DIVU","?","?","?","?",
97
   "ADD","ADDU","SUB","SUBU","AND","OR","XOR","NOR",
98
   "?","?","SLT","SLTU","?","DADDU","?","?",
99
   "TGE","TGEU","TLT","TLTU","TEQ","?","TNE","?",
100
   "?","?","?","?","?","?","?","?"
101
};
102
 
103
static char *regimm_string[]={
104
   "BLTZ","BGEZ","BLTZL","BGEZL","?","?","?","?",
105
   "TGEI","TGEIU","TLTI","TLTIU","TEQI","?","TNEI","?",
106
   "BLTZAL","BEQZAL","BLTZALL","BGEZALL","?","?","?","?",
107
   "?","?","?","?","?","?","?","?"
108
};
109
 
110 194 rhoads
static unsigned long HWMemory[8];
111 41 rhoads
 
112 137 rhoads
 
113
static long mem_read(State *s, long size, unsigned long address)
114 41 rhoads
{
115 137 rhoads
   unsigned long value=0, ptr;
116
 
117 194 rhoads
   s->irqStatus |= IRQ_UART_WRITE_AVAILABLE;
118 137 rhoads
   switch(address)
119
   {
120
      case UART_READ:
121
         if(kbhit())
122
            HWMemory[0] = getch();
123 194 rhoads
         s->irqStatus &= ~IRQ_UART_READ_AVAILABLE; //clear bit
124 137 rhoads
         return HWMemory[0];
125
      case IRQ_MASK:
126
         return HWMemory[1];
127
      case IRQ_MASK + 4:
128
         Sleep(10);
129
         return 0;
130
      case IRQ_STATUS:
131
         if(kbhit())
132 194 rhoads
            s->irqStatus |= IRQ_UART_READ_AVAILABLE;
133
         return s->irqStatus;
134
      case MMU_PROCESS_ID:
135
         return s->processId;
136
      case MMU_FAULT_ADDR:
137
         return s->faultAddr;
138 137 rhoads
   }
139
 
140
   ptr = (unsigned long)s->mem + (address % MEM_SIZE);
141
 
142
   if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
143 194 rhoads
      ptr = (unsigned long)s->mem + address - 0x10000000;
144
   else if(address < 1024*8)
145
      ptr += 1024*1024;
146 137 rhoads
 
147
   switch(size)
148
   {
149
      case 4:
150
         if(address & 3)
151 194 rhoads
            printf("Unaligned access PC=0x%x address=0x%x\n", s->pc, address);
152 137 rhoads
         assert((address & 3) == 0);
153
         value = *(long*)ptr;
154 194 rhoads
         if(s->big_endian)
155 137 rhoads
            value = ntohl(value);
156 41 rhoads
         break;
157
      case 2:
158 137 rhoads
         assert((address & 1) == 0);
159
         value = *(unsigned short*)ptr;
160 194 rhoads
         if(s->big_endian)
161 137 rhoads
            value = ntohs((unsigned short)value);
162 41 rhoads
         break;
163
      case 1:
164 137 rhoads
         value = *(unsigned char*)ptr;
165 41 rhoads
         break;
166 137 rhoads
      default:
167
         printf("ERROR");
168 41 rhoads
   }
169
   return(value);
170
}
171
 
172 137 rhoads
static void mem_write(State *s, long size, long unsigned address, unsigned long value)
173 41 rhoads
{
174
   static char_count=0;
175
   unsigned long ptr;
176 137 rhoads
 
177
   switch(address)
178
   {
179
      case UART_WRITE:
180
         putch(value);
181
         return;
182
      case IRQ_MASK:
183
         HWMemory[1] = value;
184
         return;
185
      case IRQ_STATUS:
186 194 rhoads
         s->irqStatus = value;
187 137 rhoads
         return;
188 194 rhoads
      case CONFIG_REG:
189
         return;
190
      case MMU_PROCESS_ID:
191
         //printf("processId=%d\n", value);
192
         s->processId = value;
193
         return;
194 41 rhoads
   }
195 194 rhoads
   if(MMU_TLB <= address && address <= MMU_TLB+MMU_ENTRIES * 8)
196
   {
197
      //printf("TLB 0x%x 0x%x\n", address - MMU_TLB, value);
198
      ptr = (unsigned long)s->mmuEntry + address - MMU_TLB;
199
      *(int*)ptr = value;
200
      s->irqStatus &= ~IRQ_MMU;
201
      return;
202
   }
203 137 rhoads
 
204
   ptr = (unsigned long)s->mem + (address % MEM_SIZE);
205
 
206
   if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
207 194 rhoads
      ptr = (unsigned long)s->mem + address - 0x10000000;
208
   else if(address < 1024*8)
209
      ptr += 1024*1024;
210 137 rhoads
 
211
   switch(size)
212
   {
213
      case 4:
214
         assert((address & 3) == 0);
215 194 rhoads
         if(s->big_endian)
216 137 rhoads
            value = htonl(value);
217
         *(long*)ptr = value;
218 41 rhoads
         break;
219
      case 2:
220 137 rhoads
         assert((address & 1) == 0);
221 194 rhoads
         if(s->big_endian)
222 137 rhoads
            value = htons((unsigned short)value);
223
         *(short*)ptr = (unsigned short)value;
224 41 rhoads
         break;
225
      case 1:
226 137 rhoads
         *(char*)ptr = (unsigned char)value;
227 41 rhoads
         break;
228 137 rhoads
      default:
229
         printf("ERROR");
230 41 rhoads
   }
231
}
232
 
233 194 rhoads
#ifdef ENABLE_CACHE
234
/************* Optional MMU and cache implementation *************/
235
/* TAG = VirtualAddress | ProcessId | WriteableBit */
236
unsigned long mmu_lookup(State *s, unsigned long processId,
237
                         unsigned long address, int write)
238
{
239
   int i;
240
   unsigned long compare, tag;
241
 
242
   if(processId == 0 || s->userMode == 0)
243
      return address;
244
   //if(address < 0x30000000)
245
   //   return address;
246
   compare = (address & ~MMU_MASK) | (processId << 1);
247
   for(i = 0; i < MMU_ENTRIES; ++i)
248
   {
249
      tag = s->mmuEntry[i].virtualAddress;
250
      if((tag & ~1) == compare && (write == 0 || (tag & 1)))
251
         return s->mmuEntry[i].physicalAddress | (address & MMU_MASK);
252
   }
253
   //printf("\nMMUTlbMiss 0x%x PC=0x%x w=%d pid=%d user=%d\n", 
254
   //   address, s->pc, write, processId, s->userMode);
255
   //printf("m");
256
   s->exceptionId = 1;
257
   s->faultAddr = address & ~MMU_MASK;
258
   s->irqStatus |= IRQ_MMU;
259
   return address;
260
}
261
 
262
 
263
#define CACHE_SET_ASSOC_LN2   0
264
#define CACHE_SET_ASSOC       (1 << CACHE_SET_ASSOC_LN2)
265
#define CACHE_SIZE_LN2        (13 - CACHE_SET_ASSOC_LN2)  //8 KB
266
#define CACHE_SIZE            (1 << CACHE_SIZE_LN2)
267
#define CACHE_LINE_SIZE_LN2   5                           //32 bytes
268
#define CACHE_LINE_SIZE       (1 << CACHE_LINE_SIZE_LN2)
269
 
270
static long cacheData[CACHE_SET_ASSOC][CACHE_SIZE/sizeof(long)];
271
static long cacheAddr[CACHE_SET_ASSOC][CACHE_SIZE/CACHE_LINE_SIZE];
272
static long cacheSetNext;
273
static long cacheMiss, cacheWriteBack, cacheCount;
274
 
275
static void cache_init(void)
276
{
277
   int set, i;
278
   for(set = 0; set < CACHE_SET_ASSOC; ++set)
279
   {
280
      for(i = 0; i < CACHE_SIZE/CACHE_LINE_SIZE; ++i)
281
         cacheAddr[set][i] = 0xffff0000;
282
   }
283
}
284
 
285
/* Write-back cache memory tagged by virtual address and processId */
286
/* TAG = virtualAddress | processId | dirtyBit */
287
static int cache_load(State *s, unsigned long address, int write)
288
{
289
   int set, i, pid, miss, offsetAddr, offsetData, offsetMem;
290
   unsigned long addrTagMatch, addrPrevMatch=0;
291
   unsigned long addrPrev;
292
   unsigned long addressPhysical, tag;
293
 
294
   ++cacheCount;
295
   addrTagMatch = address & ~(CACHE_SIZE-1);
296
   offsetAddr = (address & (CACHE_SIZE-1)) >> CACHE_LINE_SIZE_LN2;
297
 
298
   /* Find match */
299
   miss = 1;
300
   for(set = 0; set < CACHE_SET_ASSOC; ++set)
301
   {
302
      addrPrevMatch = cacheAddr[set][offsetAddr] & ~(CACHE_SIZE-1);
303
      if(addrPrevMatch == addrTagMatch)
304
      {
305
         miss = 0;
306
         break;
307
      }
308
   }
309
 
310
   /* Cache miss? */
311
   if(miss)
312
   {
313
      ++cacheMiss;
314
      set = cacheSetNext;
315
      cacheSetNext = (cacheSetNext + 1) & (CACHE_SET_ASSOC-1);
316
   }
317
   else if(write || (address >> 28) != 0x1)
318
   {
319
      tag = cacheAddr[set][offsetAddr];
320
      pid = (tag & (CACHE_SIZE-1)) >> 1;
321
      if(pid != s->processId)
322
         miss = 1;
323
   }
324
 
325
   if(miss)
326
   {
327
      offsetData = address & (CACHE_SIZE-1) & ~(CACHE_LINE_SIZE-1);
328
 
329
      /* Cache line dirty? */
330
      if(cacheAddr[set][offsetAddr] & 1)
331
      {
332
         /* Write back cache line */
333
         tag = cacheAddr[set][offsetAddr];
334
         addrPrev = tag & ~(CACHE_SIZE-1);
335
         addrPrev |= address & (CACHE_SIZE-1);
336
         pid = (tag & (CACHE_SIZE-1)) >> 1;
337
         addressPhysical = mmu_lookup(s, pid, addrPrev, 1);   //virtual->physical
338
         if(s->exceptionId)
339
            return 0;
340
         offsetMem = addressPhysical & ~(CACHE_LINE_SIZE-1);
341
         for(i = 0; i < CACHE_LINE_SIZE; i += 4)
342
            mem_write(s, 4, offsetMem + i, cacheData[set][(offsetData + i) >> 2]);
343
         ++cacheWriteBack;
344
      }
345
 
346
      /* Read cache line */
347
      addressPhysical = mmu_lookup(s, s->processId, address, write); //virtual->physical
348
      if(s->exceptionId)
349
         return 0;
350
      offsetMem = addressPhysical & ~(CACHE_LINE_SIZE-1);
351
      cacheAddr[set][offsetAddr] = addrTagMatch;
352
      for(i = 0; i < CACHE_LINE_SIZE; i += 4)
353
         cacheData[set][(offsetData + i) >> 2] = mem_read(s, 4, offsetMem + i);
354
   }
355
   cacheAddr[set][offsetAddr] |= write;
356
   return set;
357
}
358
 
359
static long cache_read(State *s, long size, unsigned long address)
360
{
361
   int set, offset;
362
   long value;
363
 
364
   if((address >> 28) == 0x2) // && (s->processId == 0 || s->userMode == 0))
365
      return mem_read(s, size, address);
366
 
367
   set = cache_load(s, address, 0);
368
   if(s->exceptionId)
369
      return 0;
370
   offset = (address & (CACHE_SIZE-1)) >> 2;
371
   value = cacheData[set][offset];
372
   if(s->big_endian)
373
      address ^= 3;
374
   switch(size)
375
   {
376
      case 2:
377
         value = (value >> ((address & 2) << 3)) & 0xffff;
378
         break;
379
      case 1:
380
         value = (value >> ((address & 3) << 3)) & 0xff;
381
         break;
382
   }
383
   return value;
384
}
385
 
386
static void cache_write(State *s, long size, long unsigned address, unsigned long value)
387
{
388
   int set, offset;
389
   unsigned long mask;
390
 
391
   if((address >> 28) == 0x2) // && (s->processId == 0 || s->userMode == 0))
392
   {
393
      mem_write(s, size, address, value);
394
      return;
395
   }
396
 
397
   set = cache_load(s, address, 1);
398
   if(s->exceptionId)
399
      return;
400
   offset = (address & (CACHE_SIZE-1)) >> 2;
401
   if(s->big_endian)
402
      address ^= 3;
403
   switch(size)
404
   {
405
      case 2:
406
         value &= 0xffff;
407
         value |= value << 16;
408
         mask = 0xffff << ((address & 2) << 3);
409
         break;
410
      case 1:
411
         value &= 0xff;
412
         value |= (value << 8) | (value << 16) | (value << 24);
413
         mask = 0xff << ((address & 3) << 3);
414
         break;
415
      case 4:
416
      default:
417
         mask = 0xffffffff;
418
         break;
419
   }
420
   cacheData[set][offset] = (value & mask) | (cacheData[set][offset] & ~mask);
421
}
422
 
423
#define mem_read cache_read
424
#define mem_write cache_write
425
/************* End optional cache implementation *************/
426
#else
427
static void cache_init(void) {}
428
#endif
429
 
430 137 rhoads
void mult_big(unsigned long a,
431
              unsigned long b,
432
              unsigned long *hi,
433
              unsigned long *lo)
434 41 rhoads
{
435 137 rhoads
   unsigned long ahi, alo, bhi, blo;
436
   unsigned long c0, c1, c2;
437
   unsigned long c1_a, c1_b;
438 52 rhoads
 
439 137 rhoads
   ahi = a >> 16;
440
   alo = a & 0xffff;
441
   bhi = b >> 16;
442
   blo = b & 0xffff;
443 52 rhoads
 
444 137 rhoads
   c0 = alo * blo;
445
   c1_a = ahi * blo;
446
   c1_b = alo * bhi;
447
   c2 = ahi * bhi;
448 52 rhoads
 
449 137 rhoads
   c2 += (c1_a >> 16) + (c1_b >> 16);
450
   c1 = (c1_a & 0xffff) + (c1_b & 0xffff) + (c0 >> 16);
451
   c2 += (c1 >> 16);
452
   c0 = (c1 << 16) + (c0 & 0xffff);
453
   *hi = c2;
454
   *lo = c0;
455 41 rhoads
}
456
 
457 137 rhoads
void mult_big_signed(long a,
458
                     long b,
459
                     unsigned long *hi,
460
                     unsigned long *lo)
461
{
462
   unsigned long ahi, alo, bhi, blo;
463
   unsigned long c0, c1, c2;
464
   unsigned long c1_a, c1_b;
465
 
466
   ahi = a >> 16;
467
   alo = a & 0xffff;
468
   bhi = b >> 16;
469
   blo = b & 0xffff;
470
 
471
   c0 = alo * blo;
472
   c1_a = ahi * blo;
473
   c1_b = alo * bhi;
474
   c2 = ahi * bhi;
475
 
476
   c2 += (c1_a >> 16) + (c1_b >> 16);
477
   c1 = (c1_a & 0xffff) + (c1_b & 0xffff) + (c0 >> 16);
478
   c2 += (c1 >> 16);
479
   c0 = (c1 << 16) + (c0 & 0xffff);
480
   *hi = c2;
481
   *lo = c0;
482
}
483
 
484 43 rhoads
//execute one cycle of a Plasma CPU
485 137 rhoads
void cycle(State *s, int show_mode)
486 41 rhoads
{
487
   unsigned long opcode;
488 137 rhoads
   unsigned long op, rs, rt, rd, re, func, imm, target;
489 194 rhoads
   long imm_shift, branch=0, lbranch=2, skip2=0;
490 41 rhoads
   long *r=s->r;
491
   unsigned long *u=(unsigned long*)s->r;
492 194 rhoads
   unsigned long ptr, epc, rSave;
493
 
494 137 rhoads
   opcode = mem_read(s, 4, s->pc);
495
   op = (opcode >> 26) & 0x3f;
496
   rs = (opcode >> 21) & 0x1f;
497
   rt = (opcode >> 16) & 0x1f;
498
   rd = (opcode >> 11) & 0x1f;
499
   re = (opcode >> 6) & 0x1f;
500
   func = opcode & 0x3f;
501
   imm = opcode & 0xffff;
502
   imm_shift = (((long)(short)imm) << 2) - 4;
503
   target = (opcode << 6) >> 4;
504
   ptr = (short)imm + r[rs];
505
   r[0] = 0;
506
   if(show_mode)
507
   {
508 194 rhoads
      printf("%8.8lx %8.8lx ", s->pc, opcode);
509 137 rhoads
      if(op == 0)
510
         printf("%8s ", special_string[func]);
511
      else if(op == 1)
512
         printf("%8s ", regimm_string[rt]);
513
      else
514
         printf("%8s ", opcode_string[op]);
515
      printf("$%2.2ld $%2.2ld $%2.2ld $%2.2ld ", rs, rt, rd, re);
516 194 rhoads
      printf("%4.4lx", imm);
517
      if(show_mode == 1)
518
         printf(" r[%2.2d]=%8.8x r[%2.2d]=%8.8x", rs, r[rs], rt, r[rt]);
519
      printf("\n");
520 41 rhoads
   }
521 137 rhoads
   if(show_mode > 5)
522 41 rhoads
      return;
523 194 rhoads
   epc = s->pc + 4;
524
   if(s->pc_next != s->pc + 4)
525
      epc |= 2;  //branch delay slot
526 137 rhoads
   s->pc = s->pc_next;
527
   s->pc_next = s->pc_next + 4;
528
   if(s->skip)
529
   {
530
      s->skip = 0;
531
      return;
532 41 rhoads
   }
533 194 rhoads
   rSave = r[rt];
534 137 rhoads
   switch(op)
535
   {
536 41 rhoads
      case 0x00:/*SPECIAL*/
537 137 rhoads
         switch(func)
538
         {
539 41 rhoads
            case 0x00:/*SLL*/  r[rd]=r[rt]<<re;          break;
540
            case 0x02:/*SRL*/  r[rd]=u[rt]>>re;          break;
541
            case 0x03:/*SRA*/  r[rd]=r[rt]>>re;          break;
542
            case 0x04:/*SLLV*/ r[rd]=r[rt]<<r[rs];       break;
543
            case 0x06:/*SRLV*/ r[rd]=u[rt]>>r[rs];       break;
544
            case 0x07:/*SRAV*/ r[rd]=r[rt]>>r[rs];       break;
545
            case 0x08:/*JR*/   s->pc_next=r[rs];         break;
546
            case 0x09:/*JALR*/ r[rd]=s->pc_next; s->pc_next=r[rs]; break;
547
            case 0x0a:/*MOVZ*/ if(!r[rt]) r[rd]=r[rs];   break;  /*IV*/
548
            case 0x0b:/*MOVN*/ if(r[rt]) r[rd]=r[rs];    break;  /*IV*/
549 194 rhoads
            case 0x0c:/*SYSCALL*/ epc|=1; s->exceptionId=1; break;
550
            case 0x0d:/*BREAK*/   epc|=1; s->exceptionId=1; break;
551 137 rhoads
            case 0x0f:/*SYNC*/ s->wakeup=1;              break;
552 41 rhoads
            case 0x10:/*MFHI*/ r[rd]=s->hi;              break;
553
            case 0x11:/*FTHI*/ s->hi=r[rs];              break;
554
            case 0x12:/*MFLO*/ r[rd]=s->lo;              break;
555
            case 0x13:/*MTLO*/ s->lo=r[rs];              break;
556 137 rhoads
            case 0x18:/*MULT*/ mult_big_signed(r[rs],r[rt],&s->hi,&s->lo); break;
557 194 rhoads
            case 0x19:/*MULTU*/ mult_big(r[rs],r[rt],&s->hi,&s->lo); break;
558 41 rhoads
            case 0x1a:/*DIV*/  s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; break;
559
            case 0x1b:/*DIVU*/ s->lo=u[rs]/u[rt]; s->hi=u[rs]%u[rt]; break;
560
            case 0x20:/*ADD*/  r[rd]=r[rs]+r[rt];        break;
561
            case 0x21:/*ADDU*/ r[rd]=r[rs]+r[rt];        break;
562
            case 0x22:/*SUB*/  r[rd]=r[rs]-r[rt];        break;
563
            case 0x23:/*SUBU*/ r[rd]=r[rs]-r[rt];        break;
564
            case 0x24:/*AND*/  r[rd]=r[rs]&r[rt];        break;
565
            case 0x25:/*OR*/   r[rd]=r[rs]|r[rt];        break;
566
            case 0x26:/*XOR*/  r[rd]=r[rs]^r[rt];        break;
567
            case 0x27:/*NOR*/  r[rd]=~(r[rs]|r[rt]);     break;
568
            case 0x2a:/*SLT*/  r[rd]=r[rs]<r[rt];        break;
569
            case 0x2b:/*SLTU*/ r[rd]=u[rs]<u[rt];        break;
570
            case 0x2d:/*DADDU*/r[rd]=r[rs]+u[rt];        break;
571
            case 0x31:/*TGEU*/ break;
572
            case 0x32:/*TLT*/  break;
573
            case 0x33:/*TLTU*/ break;
574
            case 0x34:/*TEQ*/  break;
575
            case 0x36:/*TNE*/  break;
576 194 rhoads
            default: printf("ERROR0(*0x%x~0x%x)\n", s->pc, opcode);
577 41 rhoads
               s->wakeup=1;
578
         }
579
         break;
580
      case 0x01:/*REGIMM*/
581
         switch(rt) {
582
            case 0x10:/*BLTZAL*/ r[31]=s->pc_next;
583 137 rhoads
            case 0x00:/*BLTZ*/   branch=r[rs]<0;    break;
584 41 rhoads
            case 0x11:/*BGEZAL*/ r[31]=s->pc_next;
585 137 rhoads
            case 0x01:/*BGEZ*/   branch=r[rs]>=0;   break;
586 41 rhoads
            case 0x12:/*BLTZALL*/r[31]=s->pc_next;
587 137 rhoads
            case 0x02:/*BLTZL*/  lbranch=r[rs]<0;   break;
588 41 rhoads
            case 0x13:/*BGEZALL*/r[31]=s->pc_next;
589 137 rhoads
            case 0x03:/*BGEZL*/  lbranch=r[rs]>=0;  break;
590 41 rhoads
            default: printf("ERROR1\n"); s->wakeup=1;
591
          }
592
         break;
593
      case 0x03:/*JAL*/    r[31]=s->pc_next;
594
      case 0x02:/*J*/      s->pc_next=(s->pc&0xf0000000)|target; break;
595
      case 0x04:/*BEQ*/    branch=r[rs]==r[rt];     break;
596
      case 0x05:/*BNE*/    branch=r[rs]!=r[rt];     break;
597
      case 0x06:/*BLEZ*/   branch=r[rs]<=0;         break;
598
      case 0x07:/*BGTZ*/   branch=r[rs]>0;          break;
599
      case 0x08:/*ADDI*/   r[rt]=r[rs]+(short)imm;  break;
600
      case 0x09:/*ADDIU*/  u[rt]=u[rs]+(short)imm;  break;
601
      case 0x0a:/*SLTI*/   r[rt]=r[rs]<(short)imm;  break;
602
      case 0x0b:/*SLTIU*/  u[rt]=u[rs]<(unsigned long)(short)imm; break;
603
      case 0x0c:/*ANDI*/   r[rt]=r[rs]&imm;         break;
604
      case 0x0d:/*ORI*/    r[rt]=r[rs]|imm;         break;
605
      case 0x0e:/*XORI*/   r[rt]=r[rs]^imm;         break;
606
      case 0x0f:/*LUI*/    r[rt]=(imm<<16);         break;
607 194 rhoads
      case 0x10:/*COP0*/
608
         if((opcode & (1<<23)) == 0)  //move from CP0
609
         {
610
            if(rd == 12)
611
               r[rt]=s->status;
612
            else
613
               r[rt]=s->epc;
614
         }
615
         else                         //move to CP0
616
         {
617
            s->status=r[rt]&1;
618
            if(s->processId && (r[rt]&2))
619
            {
620
               s->userMode|=r[rt]&2;
621
               //printf("CpuStatus=%d %d %d\n", r[rt], s->status, s->userMode);
622
               //s->wakeup = 1;
623
               //printf("pc=0x%x\n", epc);
624
            }
625
         }
626
         break;
627 41 rhoads
//      case 0x11:/*COP1*/ break;
628
//      case 0x12:/*COP2*/ break;
629
//      case 0x13:/*COP3*/ break;
630
      case 0x14:/*BEQL*/   lbranch=r[rs]==r[rt];    break;
631
      case 0x15:/*BNEL*/   lbranch=r[rs]!=r[rt];    break;
632
      case 0x16:/*BLEZL*/  lbranch=r[rs]<=0;        break;
633
      case 0x17:/*BGTZL*/  lbranch=r[rs]>0;         break;
634
//      case 0x1c:/*MAD*/  break;   /*IV*/
635
      case 0x20:/*LB*/   r[rt]=(signed char)mem_read(s,1,ptr);  break;
636
      case 0x21:/*LH*/   r[rt]=(signed short)mem_read(s,2,ptr); break;
637 241 rhoads
      case 0x22:/*LWL*/
638
                         //target=8*(ptr&3);
639
                         //r[rt]=(r[rt]&~(0xffffffff<<target))|
640
                         //      (mem_read(s,4,ptr&~3)<<target); break;
641 41 rhoads
      case 0x23:/*LW*/   r[rt]=mem_read(s,4,ptr);   break;
642
      case 0x24:/*LBU*/  r[rt]=(unsigned char)mem_read(s,1,ptr); break;
643
      case 0x25:/*LHU*/  r[rt]=(unsigned short)mem_read(s,2,ptr); break;
644 241 rhoads
      case 0x26:/*LWR*/
645
                         //target=32-8*(ptr&3);
646
                         //r[rt]=(r[rt]&~((unsigned long)0xffffffff>>target))|
647
                         //((unsigned long)mem_read(s,4,ptr&~3)>>target); 
648
                         break;
649 41 rhoads
      case 0x28:/*SB*/   mem_write(s,1,ptr,r[rt]);  break;
650
      case 0x29:/*SH*/   mem_write(s,2,ptr,r[rt]);  break;
651 241 rhoads
      case 0x2a:/*SWL*/
652
                         //mem_write(s,1,ptr,r[rt]>>24);  
653
                         //mem_write(s,1,ptr+1,r[rt]>>16);
654
                         //mem_write(s,1,ptr+2,r[rt]>>8);
655
                         //mem_write(s,1,ptr+3,r[rt]); break;
656 41 rhoads
      case 0x2b:/*SW*/   mem_write(s,4,ptr,r[rt]);  break;
657
      case 0x2e:/*SWR*/  break; //fixme
658
      case 0x2f:/*CACHE*/break;
659
      case 0x30:/*LL*/   r[rt]=mem_read(s,4,ptr);   break;
660
//      case 0x31:/*LWC1*/ break;
661
//      case 0x32:/*LWC2*/ break;
662
//      case 0x33:/*LWC3*/ break;
663
//      case 0x35:/*LDC1*/ break;
664
//      case 0x36:/*LDC2*/ break;
665
//      case 0x37:/*LDC3*/ break;
666
//      case 0x38:/*SC*/     *(long*)ptr=r[rt]; r[rt]=1; break;
667
      case 0x38:/*SC*/     mem_write(s,4,ptr,r[rt]); r[rt]=1; break;
668
//      case 0x39:/*SWC1*/ break;
669
//      case 0x3a:/*SWC2*/ break;
670
//      case 0x3b:/*SWC3*/ break;
671
//      case 0x3d:/*SDC1*/ break;
672
//      case 0x3e:/*SDC2*/ break;
673
//      case 0x3f:/*SDC3*/ break;
674 194 rhoads
      default: printf("ERROR2 address=0x%x opcode=0x%x\n", s->pc, opcode);
675
         s->wakeup=1;
676 41 rhoads
   }
677 194 rhoads
   s->pc_next += (branch || lbranch == 1) ? imm_shift : 0;
678
   s->pc_next &= ~3;
679
   s->skip = (lbranch == 0) | skip2;
680
 
681
   if(s->exceptionId)
682
   {
683
      r[rt] = rSave;
684
      s->epc = epc;
685
      s->pc_next = 0x3c;
686
      s->skip = 1;
687
      s->exceptionId = 0;
688
      s->userMode = 0;
689
      //s->wakeup = 1;
690
      return;
691
   }
692 41 rhoads
}
693
 
694
void show_state(State *s)
695
{
696
   long i,j;
697 194 rhoads
   printf("pid=%d userMode=%d, epc=0x%x\n", s->processId, s->userMode, s->epc);
698 137 rhoads
   for(i = 0; i < 4; ++i)
699
   {
700
      printf("%2.2ld ", i * 8);
701
      for(j = 0; j < 8; ++j)
702
      {
703
         printf("%8.8lx ", s->r[i*8+j]);
704 41 rhoads
      }
705
      printf("\n");
706
   }
707 194 rhoads
   //printf("%8.8lx %8.8lx %8.8lx %8.8lx\n", s->pc, s->pc_next, s->hi, s->lo);
708 137 rhoads
   j = s->pc;
709
   for(i = -4; i <= 8; ++i)
710
   {
711
      printf("%c", i==0 ? '*' : ' ');
712
      s->pc = j + i * 4;
713
      cycle(s, 10);
714 41 rhoads
   }
715 137 rhoads
   s->pc = j;
716 41 rhoads
}
717
 
718
void do_debug(State *s)
719
{
720
   int ch;
721 137 rhoads
   long i, j=0, watch=0, addr;
722
   s->pc_next = s->pc + 4;
723
   s->skip = 0;
724
   s->wakeup = 0;
725 41 rhoads
   show_state(s);
726 194 rhoads
   ch = ' ';
727 137 rhoads
   for(;;)
728
   {
729 194 rhoads
      if(ch != 'n')
730
      {
731
         if(watch)
732
            printf("0x%8.8lx=0x%8.8lx\n", watch, mem_read(s, 4, watch));
733
         printf("1=Debug 2=Trace 3=Step 4=BreakPt 5=Go 6=Memory ");
734
         printf("7=Watch 8=Jump 9=Quit> ");
735
      }
736 137 rhoads
      ch = getch();
737 194 rhoads
      if(ch != 'n')
738
         printf("\n");
739 137 rhoads
      switch(ch)
740
      {
741
      case '1': case 'd': case ' ':
742 194 rhoads
         cycle(s, 0); show_state(s); break;
743
      case 'n':
744
         cycle(s, 1); break;
745 137 rhoads
      case '2': case 't':
746 194 rhoads
         cycle(s, 0); printf("*"); cycle(s, 10); break;
747 41 rhoads
      case '3': case 's':
748
         printf("Count> ");
749 137 rhoads
         scanf("%ld", &j);
750
         for(i = 0; i < j; ++i)
751 194 rhoads
            cycle(s, 1);
752 41 rhoads
         show_state(s);
753
         break;
754
      case '4': case 'b':
755
         printf("Line> ");
756 137 rhoads
         scanf("%lx", &j);
757
         printf("break point=0x%x\n", j);
758 41 rhoads
         break;
759
      case '5': case 'g':
760 137 rhoads
         s->wakeup = 0;
761
         cycle(s, 0);
762
         while(s->wakeup == 0)
763
         {
764
            if(s->pc == j)
765
               break;
766
            cycle(s, 0);
767 41 rhoads
         }
768
         show_state(s);
769
         break;
770 194 rhoads
      case 'G':
771
         s->wakeup = 0;
772
         cycle(s, 1);
773
         while(s->wakeup == 0)
774
         {
775
            if(s->pc == j)
776
               break;
777
            cycle(s, 1);
778
         }
779
         show_state(s);
780
         break;
781 41 rhoads
      case '6': case 'm':
782
         printf("Memory> ");
783 137 rhoads
         scanf("%lx", &j);
784
         for(i = 0; i < 8; ++i)
785
         {
786
            printf("%8.8lx ", mem_read(s, 4, j+i*4));
787 41 rhoads
         }
788
         printf("\n");
789
         break;
790
      case '7': case 'w':
791
         printf("Watch> ");
792 137 rhoads
         scanf("%lx", &watch);
793 41 rhoads
         break;
794
      case '8': case 'j':
795
         printf("Jump> ");
796 137 rhoads
         scanf("%lx", &addr);
797
         s->pc = addr;
798
         s->pc_next = addr + 4;
799 41 rhoads
         show_state(s);
800
         break;
801 137 rhoads
      case '9': case 'q':
802
         return;
803 41 rhoads
      }
804
   }
805
}
806
/************************************************************/
807
 
808
int main(int argc,char *argv[])
809
{
810 137 rhoads
   State state, *s=&state;
811 41 rhoads
   FILE *in;
812 137 rhoads
   long bytes, index;
813 43 rhoads
   printf("Plasma emulator\n");
814 137 rhoads
   memset(s, 0, sizeof(State));
815
   s->big_endian = 1;
816
   s->mem = (unsigned char*)malloc(MEM_SIZE);
817 194 rhoads
   memset(s->mem, 0, MEM_SIZE);
818 137 rhoads
   if(argc <= 1)
819
   {
820 41 rhoads
      printf("   Usage:  mlite file.exe\n");
821
      printf("           mlite file.exe B   {for big_endian}\n");
822 137 rhoads
      printf("           mlite file.exe L   {for little_endian}\n");
823 41 rhoads
      printf("           mlite file.exe BD  {disassemble big_endian}\n");
824 137 rhoads
      printf("           mlite file.exe LD  {disassemble little_endian}\n");
825
 
826 41 rhoads
      return 0;
827
   }
828 137 rhoads
   in = fopen(argv[1], "rb");
829
   if(in == NULL)
830
   {
831
      printf("Can't open file %s!\n",argv[1]);
832
      getch();
833
      return(0);
834
   }
835
   bytes = fread(s->mem, 1, MEM_SIZE, in);
836 41 rhoads
   fclose(in);
837 241 rhoads
   memcpy(s->mem + 1024*1024, s->mem, 1024*8);  //internal 8KB SRAM
838 137 rhoads
   printf("Read %ld bytes.\n", bytes);
839 194 rhoads
   cache_init();
840 137 rhoads
   if(argc == 3 && argv[2][0] == 'B')
841
   {
842 41 rhoads
      printf("Big Endian\n");
843 137 rhoads
      s->big_endian = 1;
844 41 rhoads
   }
845 137 rhoads
   if(argc == 3 && argv[2][0] == 'L')
846
   {
847 41 rhoads
      printf("Big Endian\n");
848 137 rhoads
      s->big_endian = 0;
849
   }
850 194 rhoads
   s->processId = 0;
851 137 rhoads
   if(argc == 3 && argv[2][0] == 'S')
852
   {  /*make big endian*/
853
      printf("Big Endian\n");
854
      for(index = 0; index < bytes+3; index += 4)
855
      {
856
         *(unsigned long*)&s->mem[index] = htonl(*(unsigned long*)&s->mem[index]);
857 41 rhoads
      }
858 137 rhoads
      in = fopen("big.exe", "wb");
859
      fwrite(s->mem, bytes, 1, in);
860 41 rhoads
      fclose(in);
861
      return(0);
862
   }
863 137 rhoads
   if(argc == 3 && argv[2][1] == 'D')
864
   {  /*dump image*/
865
      for(index = 0; index < bytes; index += 4) {
866
         s->pc = index;
867
         cycle(s, 10);
868 41 rhoads
      }
869
      free(s->mem);
870
      return(0);
871
   }
872 137 rhoads
   s->pc = 0x0;
873
   index = mem_read(s, 4, 0);
874
   if(index == 0x3c1c1000)
875
      s->pc = 0x10000000;
876 41 rhoads
   do_debug(s);
877
   free(s->mem);
878
   return(0);
879
}
880
 

powered by: WebSVN 2.1.0

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