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

Subversion Repositories plasma

[/] [plasma/] [tags/] [arelease/] [tools/] [mips.c] - Blame information for rev 393

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

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

powered by: WebSVN 2.1.0

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