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

Subversion Repositories plasma

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

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

powered by: WebSVN 2.1.0

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