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

Subversion Repositories mlite

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

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
--------------------------------------------------------------------*/
13
#include <stdio.h>
14
#include <stdlib.h>
15
#include <string.h>
16
#include <ctype.h>
17
 
18
#define MEM_SIZE (1024*1024*2)
19
#define ntohs(A) ( ((A)>>8) | (((A)&0xff)<<8) )
20
#define htons(A) ntohs(A)
21
#define ntohl(A) ( ((A)>>24) | (((A)&0xff0000)>>8) | (((A)&0xff00)<<8) | ((A)<<24) )
22
#define htonl(A) ntohl(A)
23
 
24 104 rhoads
// int getch(void);
25
#define getch getchar
26 41 rhoads
 
27
typedef struct {
28
   long r[32];
29
   long pc,pc_next;
30
   long hi;
31
   long lo;
32
   long skip;
33
   char *mem;
34
   long wakeup;
35
   long big_endian;
36
} State;
37
 
38
static char *opcode_string[]={
39
   "SPECIAL","REGIMM","J","JAL","BEQ","BNE","BLEZ","BGTZ",
40
   "ADDI","ADDIU","SLTI","SLTIU","ANDI","ORI","XORI","LUI",
41
   "COP0","COP1","COP2","COP3","BEQL","BNEL","BLEZL","BGTZL",
42
   "?","?","?","?","?","?","?","?",
43
   "LB","LH","LWL","LW","LBU","LHU","LWR","?",
44
   "SB","SH","SWL","SW","?","?","SWR","CACHE",
45
   "LL","LWC1","LWC2","LWC3","?","LDC1","LDC2","LDC3"
46
   "SC","SWC1","SWC2","SWC3","?","SDC1","SDC2","SDC3"
47
};
48
 
49
static char *special_string[]={
50
   "SLL","?","SRL","SRA","SLLV","?","SRLV","SRAV",
51
   "JR","JALR","MOVZ","MOVN","SYSCALL","BREAK","?","SYNC",
52
   "MFHI","MTHI","MFLO","MTLO","?","?","?","?",
53
   "MULT","MULTU","DIV","DIVU","?","?","?","?",
54
   "ADD","ADDU","SUB","SUBU","AND","OR","XOR","NOR",
55
   "?","?","SLT","SLTU","?","DADDU","?","?",
56
   "TGE","TGEU","TLT","TLTU","TEQ","?","TNE","?",
57
   "?","?","?","?","?","?","?","?"
58
};
59
 
60
static char *regimm_string[]={
61
   "BLTZ","BGEZ","BLTZL","BGEZL","?","?","?","?",
62
   "TGEI","TGEIU","TLTI","TLTIU","TEQI","?","TNEI","?",
63
   "BLTZAL","BEQZAL","BLTZALL","BGEZALL","?","?","?","?",
64
   "?","?","?","?","?","?","?","?"
65
};
66
 
67
static long big_endian=0;
68
 
69
static long mem_read(State *s,long size,unsigned long address)
70
{
71
   unsigned long value=0,ptr;
72
   address%=MEM_SIZE;
73
   ptr=(long)s->mem+address;
74
   switch(size) {
75
      case 4: value=*(long*)ptr;
76
         if(big_endian) value=ntohl(value);
77
         break;
78
      case 2:
79
         value=*(unsigned short*)ptr;
80
         if(big_endian) value=ntohs((unsigned short)value);
81
         break;
82
      case 1:
83
         value=*(unsigned char*)ptr;
84
         break;
85
      default: printf("ERROR");
86
   }
87
   return(value);
88
}
89
 
90
static void mem_write(State *s,long size,long unsigned address,unsigned long value)
91
{
92
   static char_count=0;
93
   unsigned long ptr;
94
   if(address==0xffff) {          //UART write register at 0xffff
95
      value&=0xff;
96
      if(isprint(value)) {
97
         printf("%c",value);
98
         if(++char_count>=72) {
99
            printf("\n");
100
            char_count=0;
101
         }
102
      } else if(value=='\n') {
103
         printf("\n");
104
         char_count=0;
105
      } else {
106
         printf(".");
107
      }
108
   }
109
   address%=MEM_SIZE;
110
   ptr=(long)s->mem+address;
111
   switch(size) {
112
      case 4: if(big_endian) value=htonl(value);
113
         *(long*)ptr=value;
114
         break;
115
      case 2:
116
         if(big_endian) {
117
            value=htons((unsigned short)value);
118
         }
119
         *(short*)ptr=(unsigned short)value;
120
         break;
121
      case 1:
122
         *(char*)ptr=(unsigned char)value;
123
         break;
124
      default: printf("ERROR");
125
   }
126
}
127
 
128
void mult_big(unsigned long a,unsigned long b,
129
              unsigned long *hi,unsigned long *lo)
130
{
131
   unsigned long ahi,alo,bhi,blo;
132 52 rhoads
   unsigned long c0,c1,c2,c3;
133
   unsigned long c1_a,c1_b,c2_a,c2_b;
134 41 rhoads
   ahi=a>>16;
135
   alo=a&0xffff;
136
   bhi=b>>16;
137
   blo=b&0xffff;
138 52 rhoads
 
139
   c0=alo*blo;
140
   c1_a=ahi*blo;
141
   c1_b=alo*bhi;
142
   c2=ahi*bhi;
143
 
144
 
145
   c2+=(c1_a>>16)+(c1_b>>16);
146
   c1=(c1_a&0xffff)+(c1_b&0xffff)+(c0>>16);
147
   c0&=0xffff;
148
   c2+=(c1>>16);
149
   c1&=0xffff;
150
   *hi=c2;
151
   *lo=(c1<<16)+c0;
152 41 rhoads
}
153
 
154 43 rhoads
//execute one cycle of a Plasma CPU
155 41 rhoads
void cycle(State *s,int show_mode)
156
{
157
   unsigned long opcode;
158
   unsigned long op,rs,rt,rd,re,func,imm,target;
159
   long imm_shift,branch=0,lbranch=2;
160
   long *r=s->r;
161
   unsigned long *u=(unsigned long*)s->r;
162
   unsigned long ptr;
163
   opcode=mem_read(s,4,s->pc);
164
   op=(opcode>>26)&0x3f;
165
   rs=(opcode>>21)&0x1f;
166
   rt=(opcode>>16)&0x1f;
167
   rd=(opcode>>11)&0x1f;
168
   re=(opcode>>6)&0x1f;
169
   func=opcode&0x3f;
170
   imm=opcode&0xffff;
171
   imm_shift=(((long)(short)imm)<<2)-4;
172
   target=(opcode<<6)>>4;
173
   ptr=(short)imm+r[rs];
174
   r[0]=0;
175
   if(show_mode) {
176
      printf("%8.8lx %8.8lx ",s->pc,opcode);
177
      if(op==0) printf("%8s ",special_string[func]);
178
      else if(op==1) printf("%8s ",regimm_string[rt]);
179
      else printf("%8s ",opcode_string[op]);
180
      printf("$%2.2ld $%2.2ld $%2.2ld $%2.2ld ",rs,rt,rd,re);
181
      printf("%4.4lx\n",imm);
182
   }
183
   if(show_mode>5) return;
184
   s->pc=s->pc_next;
185
   s->pc_next=s->pc_next+4;
186
   if(s->skip) {
187
      s->skip=0;
188
      return;
189
   }
190
   switch(op) {
191
      case 0x00:/*SPECIAL*/
192
         switch(func) {
193
            case 0x00:/*SLL*/  r[rd]=r[rt]<<re;          break;
194
            case 0x02:/*SRL*/  r[rd]=u[rt]>>re;          break;
195
            case 0x03:/*SRA*/  r[rd]=r[rt]>>re;          break;
196
            case 0x04:/*SLLV*/ r[rd]=r[rt]<<r[rs];       break;
197
            case 0x06:/*SRLV*/ r[rd]=u[rt]>>r[rs];       break;
198
            case 0x07:/*SRAV*/ r[rd]=r[rt]>>r[rs];       break;
199
            case 0x08:/*JR*/   s->pc_next=r[rs];         break;
200
            case 0x09:/*JALR*/ r[rd]=s->pc_next; s->pc_next=r[rs]; break;
201
            case 0x0a:/*MOVZ*/ if(!r[rt]) r[rd]=r[rs];   break;  /*IV*/
202
            case 0x0b:/*MOVN*/ if(r[rt]) r[rd]=r[rs];    break;  /*IV*/
203
            case 0x0c:/*SYSCALL*/                        break;
204
            case 0x0d:/*BREAK*/ s->wakeup=1; break;
205
            case 0x0f:/*SYNC*/ s->wakeup=1; break;
206
            case 0x10:/*MFHI*/ r[rd]=s->hi;              break;
207
            case 0x11:/*FTHI*/ s->hi=r[rs];              break;
208
            case 0x12:/*MFLO*/ r[rd]=s->lo;              break;
209
            case 0x13:/*MTLO*/ s->lo=r[rs];              break;
210
            case 0x18:/*MULT*/
211
            case 0x19:/*MULTU*/ //s->lo=r[rs]*r[rt]; s->hi=0; break;
212
                               mult_big(r[rs],r[rt],&s->hi,&s->lo); break;
213
            case 0x1a:/*DIV*/  s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; break;
214
            case 0x1b:/*DIVU*/ s->lo=u[rs]/u[rt]; s->hi=u[rs]%u[rt]; break;
215
            case 0x20:/*ADD*/  r[rd]=r[rs]+r[rt];        break;
216
            case 0x21:/*ADDU*/ r[rd]=r[rs]+r[rt];        break;
217
            case 0x22:/*SUB*/  r[rd]=r[rs]-r[rt];        break;
218
            case 0x23:/*SUBU*/ r[rd]=r[rs]-r[rt];        break;
219
            case 0x24:/*AND*/  r[rd]=r[rs]&r[rt];        break;
220
            case 0x25:/*OR*/   r[rd]=r[rs]|r[rt];        break;
221
            case 0x26:/*XOR*/  r[rd]=r[rs]^r[rt];        break;
222
            case 0x27:/*NOR*/  r[rd]=~(r[rs]|r[rt]);     break;
223
            case 0x2a:/*SLT*/  r[rd]=r[rs]<r[rt];        break;
224
            case 0x2b:/*SLTU*/ r[rd]=u[rs]<u[rt];        break;
225
            case 0x2d:/*DADDU*/r[rd]=r[rs]+u[rt];        break;
226
            case 0x31:/*TGEU*/ break;
227
            case 0x32:/*TLT*/  break;
228
            case 0x33:/*TLTU*/ break;
229
            case 0x34:/*TEQ*/  break;
230
            case 0x36:/*TNE*/  break;
231
            default: printf("ERROR0(*0x%x~0x%x)\n",s->pc,opcode);
232
               s->wakeup=1;
233
         }
234
         break;
235
      case 0x01:/*REGIMM*/
236
         switch(rt) {
237
            case 0x10:/*BLTZAL*/ r[31]=s->pc_next;
238
            case 0x00:/*BLTZ*/   branch=r[rs]<0;   break;
239
            case 0x11:/*BGEZAL*/ r[31]=s->pc_next;
240
            case 0x01:/*BGEZ*/   branch=r[rs]>=0;  break;
241
            case 0x12:/*BLTZALL*/r[31]=s->pc_next;
242
            case 0x02:/*BLTZL*/  lbranch=r[rs]<0;  break;
243
            case 0x13:/*BGEZALL*/r[31]=s->pc_next;
244
            case 0x03:/*BGEZL*/  lbranch=r[rs]>=0; break;
245
            default: printf("ERROR1\n"); s->wakeup=1;
246
          }
247
         break;
248
      case 0x03:/*JAL*/    r[31]=s->pc_next;
249
      case 0x02:/*J*/      s->pc_next=(s->pc&0xf0000000)|target; break;
250
      case 0x04:/*BEQ*/    branch=r[rs]==r[rt];     break;
251
      case 0x05:/*BNE*/    branch=r[rs]!=r[rt];     break;
252
      case 0x06:/*BLEZ*/   branch=r[rs]<=0;         break;
253
      case 0x07:/*BGTZ*/   branch=r[rs]>0;          break;
254
      case 0x08:/*ADDI*/   r[rt]=r[rs]+(short)imm;  break;
255
      case 0x09:/*ADDIU*/  u[rt]=u[rs]+(short)imm;  break;
256
      case 0x0a:/*SLTI*/   r[rt]=r[rs]<(short)imm;  break;
257
      case 0x0b:/*SLTIU*/  u[rt]=u[rs]<(unsigned long)(short)imm; break;
258
      case 0x0c:/*ANDI*/   r[rt]=r[rs]&imm;         break;
259
      case 0x0d:/*ORI*/    r[rt]=r[rs]|imm;         break;
260
      case 0x0e:/*XORI*/   r[rt]=r[rs]^imm;         break;
261
      case 0x0f:/*LUI*/    r[rt]=(imm<<16);         break;
262
      case 0x10:/*COP0*/ break;
263
//      case 0x11:/*COP1*/ break;
264
//      case 0x12:/*COP2*/ break;
265
//      case 0x13:/*COP3*/ break;
266
      case 0x14:/*BEQL*/   lbranch=r[rs]==r[rt];    break;
267
      case 0x15:/*BNEL*/   lbranch=r[rs]!=r[rt];    break;
268
      case 0x16:/*BLEZL*/  lbranch=r[rs]<=0;        break;
269
      case 0x17:/*BGTZL*/  lbranch=r[rs]>0;         break;
270
//      case 0x1c:/*MAD*/  break;   /*IV*/
271
      case 0x20:/*LB*/   r[rt]=(signed char)mem_read(s,1,ptr);  break;
272
      case 0x21:/*LH*/   r[rt]=(signed short)mem_read(s,2,ptr); break;
273
      case 0x22:/*LWL*/  rt=rt; //fixme fall through
274
      case 0x23:/*LW*/   r[rt]=mem_read(s,4,ptr);   break;
275
      case 0x24:/*LBU*/  r[rt]=(unsigned char)mem_read(s,1,ptr); break;
276
      case 0x25:/*LHU*/  r[rt]=(unsigned short)mem_read(s,2,ptr); break;
277
      case 0x26:/*LWR*/  break; //fixme
278
      case 0x28:/*SB*/   mem_write(s,1,ptr,r[rt]);  break;
279
      case 0x29:/*SH*/   mem_write(s,2,ptr,r[rt]);  break;
280
      case 0x2a:/*SWL*/  rt=rt; //fixme fall through
281
      case 0x2b:/*SW*/   mem_write(s,4,ptr,r[rt]);  break;
282
      case 0x2e:/*SWR*/  break; //fixme
283
      case 0x2f:/*CACHE*/break;
284
      case 0x30:/*LL*/   r[rt]=mem_read(s,4,ptr);   break;
285
//      case 0x31:/*LWC1*/ break;
286
//      case 0x32:/*LWC2*/ break;
287
//      case 0x33:/*LWC3*/ break;
288
//      case 0x35:/*LDC1*/ break;
289
//      case 0x36:/*LDC2*/ break;
290
//      case 0x37:/*LDC3*/ break;
291
//      case 0x38:/*SC*/     *(long*)ptr=r[rt]; r[rt]=1; break;
292
      case 0x38:/*SC*/     mem_write(s,4,ptr,r[rt]); r[rt]=1; break;
293
//      case 0x39:/*SWC1*/ break;
294
//      case 0x3a:/*SWC2*/ break;
295
//      case 0x3b:/*SWC3*/ break;
296
//      case 0x3d:/*SDC1*/ break;
297
//      case 0x3e:/*SDC2*/ break;
298
//      case 0x3f:/*SDC3*/ break;
299
      default: printf("ERROR2 address=0x%x opcode=0x%x\n",
300
         s->pc,opcode); s->wakeup=1;
301
//         exit(0);
302
   }
303
   s->pc_next+=branch|(lbranch==1)?imm_shift:0;
304
   s->skip=(lbranch==0);
305
}
306
 
307
void show_state(State *s)
308
{
309
   long i,j;
310
   for(i=0;i<4;++i) {
311
      printf("%2.2ld ",i*8);
312
      for(j=0;j<8;++j) {
313
         printf("%8.8lx ",s->r[i*8+j]);
314
      }
315
      printf("\n");
316
   }
317
   printf("%8.8lx %8.8lx %8.8lx %8.8lx\n",s->pc,s->pc_next,s->hi,s->lo);
318
   j=s->pc;
319
   for(i=-4;i<=8;++i) {
320
      printf("%c",i==0?'*':' ');
321
      s->pc=j+i*4;
322
      cycle(s,10);
323
   }
324
   s->pc=j;
325
}
326
 
327
void do_debug(State *s)
328
{
329
   int ch;
330
   long i,j=0,watch=0,addr;
331
   s->pc_next=s->pc+4;
332
   s->skip=0;
333
   s->wakeup=0;
334
   show_state(s);
335
   for(;;) {
336
      if(watch) printf("0x%8.8lx=0x%8.8lx\n",watch,mem_read(s,4,watch));
337
      printf("1=Debug 2=Trace 3=Step 4=BreakPt 5=Go 6=Memory ");
338
      printf("7=Watch 8=Jump 9=Quit> ");
339
      ch=getch();
340
      printf("\n");
341
      switch(ch) {
342
      case '1': case 'd': case ' ': cycle(s,0); show_state(s); break;
343
      case '2': case 't': cycle(s,0); printf("*"); cycle(s,10); break;
344
      case '3': case 's':
345
         printf("Count> ");
346
         scanf("%ld",&j);
347
         for(i=0;i<j;++i) cycle(s,0);
348
         show_state(s);
349
         break;
350
      case '4': case 'b':
351
         printf("Line> ");
352
         scanf("%lx",&j);
353
         break;
354
      case '5': case 'g':
355
         s->wakeup=0;
356
         while(s->wakeup==0) {
357
            if(s->pc==j) break;
358
            cycle(s,0);
359
         }
360
         show_state(s);
361
         break;
362
      case '6': case 'm':
363
         printf("Memory> ");
364
         scanf("%lx",&j);
365
         for(i=0;i<8;++i) {
366
            printf("%8.8lx ",mem_read(s,4,j+i*4));
367
         }
368
         printf("\n");
369
         break;
370
      case '7': case 'w':
371
         printf("Watch> ");
372
         scanf("%lx",&watch);
373
         break;
374
      case '8': case 'j':
375
         printf("Jump> ");
376
         scanf("%lx",&addr);
377
         s->pc=addr;
378
         s->pc_next=addr+4;
379
         show_state(s);
380
         break;
381
      case '9': case 'q': return;
382
      }
383
   }
384
}
385
/************************************************************/
386
 
387
int main(int argc,char *argv[])
388
{
389
   State state,*s=&state;
390
   FILE *in;
391
   long bytes,index;
392 43 rhoads
   printf("Plasma emulator\n");
393 41 rhoads
   memset(s,0,sizeof(State));
394
   s->big_endian=0;
395
   s->mem=malloc(MEM_SIZE);
396
   if(argc<=1) {
397
      printf("   Usage:  mlite file.exe\n");
398
      printf("           mlite file.exe B   {for big_endian}\n");
399
      printf("           mlite file.exe DD  {disassemble}\n");
400
      printf("           mlite file.exe BD  {disassemble big_endian}\n");
401
      return 0;
402
   }
403
   in=fopen(argv[1],"rb");
404
   if(in==NULL) { printf("Can't open file %s!\n",argv[1]); getch(); return(0); }
405
   bytes=fread(s->mem,1,MEM_SIZE,in);
406
   fclose(in);
407
   printf("Read %ld bytes.\n",bytes);
408
   if(argc==3&&argv[2][0]=='B') {
409
      printf("Big Endian\n");
410
      s->big_endian=1;
411
      big_endian=1;
412
   }
413
   if(argc==3&&argv[2][0]=='S') {   /*make big endian*/
414
      printf("Big Endian\n");
415
      for(index=0;index<bytes+3;index+=4) {
416
         *(unsigned long*)&s->mem[index]=htonl(*(unsigned long*)&s->mem[index]);
417
      }
418
      in=fopen("big.exe","wb");
419
      fwrite(s->mem,bytes,1,in);
420
      fclose(in);
421
      return(0);
422
   }
423
   if(argc==3&&argv[2][1]=='D') {   /*dump image*/
424
      for(index=0;index<bytes;index+=4) {
425
         s->pc=index;
426
         cycle(s,10);
427
      }
428
      free(s->mem);
429
      return(0);
430
   }
431
   s->pc=0x0;
432
   do_debug(s);
433
   free(s->mem);
434
   return(0);
435
}
436
 

powered by: WebSVN 2.1.0

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