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

Subversion Repositories plasma

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

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

powered by: WebSVN 2.1.0

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