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

Subversion Repositories c16

[/] [c16/] [trunk/] [sim/] [simulate.cc] - Blame information for rev 31

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

Line No. Rev Author Line
1 2 jsauermann
 
2
#include <stdio.h>
3
#include <assert.h>
4
#include <conio.h>
5
 
6 7 jsauermann
const bool do_log = false;
7 2 jsauermann
 
8
typedef   signed char  sc;
9
typedef   signed short ss;
10
typedef unsigned char  uc;
11
typedef unsigned short us;
12
 
13
int  simulate();
14
void print_txt(const char * txt, int imm, us op, us l, us h);
15
 
16
enum { SIZE = 0x10000 };
17
 
18
uc mem[SIZE];
19
const char * labels[SIZE];
20
 
21
FILE * out = 0;
22
FILE * log = 0;
23
 
24
int clock = 4;
25
 
26
//-----------------------------------------------------------------------------
27
int main(int argc, char *argv[])
28
{
29
   for (int i = 0; i < sizeof(mem); i++)
30
       {
31
         mem[i] = 0x00;
32
         labels[i] = 0;
33
       }
34
 
35
   assert(argc == 3 && "Too few arguments");
36
 
37
   fprintf(stderr, "Input file is %s\n", argv[1]);
38
FILE * in = fopen(argv[1], "rb");
39
   assert(in && "No binary input file");
40
 
41
   fprintf(stderr, "Symbol file is %s\n", argv[2]);
42
FILE * sym = fopen(argv[2], "r");
43
   assert(in && "No symbol file");
44
 
45
   log = fopen("..\\simulate.log", "w");
46
   assert(log);
47
   // out = fopen("..\\simulate.out", "w");
48
   out = stdout;
49
   assert(out);
50
 
51
unsigned int  sval;
52
char snam[256];
53
   while (2 == fscanf(sym, "%X %s", &sval, snam))
54
      {
55
        fprintf(log, "Symbol %4.4X = %s\n", sval, snam);
56
 
57
        if (labels[sval])    continue;
58
 
59
        char * cp = new char[strlen(snam) + 1];
60
        strcpy(cp, snam);
61
        labels[sval] = cp;
62
      }
63
 
64
const int l = fread(mem, 1, sizeof(mem), in);
65
   fprintf(stderr, "%d bytes read\n", l);
66
   assert(l > 0 && "Empty binary input file");
67
   assert(l < sizeof(mem) && "Binary input file too big");
68
 
69
   fclose(in);
70
 
71
   fprintf(stderr, "Simulation started\n");
72
 
73
const int steps = simulate();
74
   fprintf(stderr,
75
           "\nSimulation done (processor halted) after %d steps\n",
76
           steps);
77
   fclose(log);
78
}
79
//-----------------------------------------------------------------------------
80
class CPU
81
{
82
public:
83
   CPU()
84
   : PC(0), SP(0), LL(0), RR(0)
85
   {};
86
 
87
   bool Step();
88
 
89
private:
90
   static us _16(us h, us l)   { return (h << 8) | l;  };
91
 
92
   uc u8()           { imm++;   return mem[PC++];                  };
93
   sc s8()           { return u8();                                };
94
   us u16()          { uc l = u8();   return _16(u8(), l);         };
95
   ss s16()          { return u16();                               }
96
   void push8(uc v)  { mem[--SP] = v;                              };
97
   void push16(us v) { mem[--SP] = v>>8;   mem[--SP] = v;          };
98
   us pop16()        { us l = mem[SP++]; return _16(mem[SP++], l); };
99
   us pop8u()        { return (us)(uc)mem[SP++];                   };
100
   ss pop8s()        { return (ss)(sc)mem[SP++];                   };
101
   us mem16(us a)    { return _16(mem[a + 1], mem[a]);             };
102
   void mem16(us a, us v)   { mem[a] = v; mem[a+1] = v >> 8;       };
103
   static us yes(us x) { if (x) return 0xFFFF;   return 0;         };
104
 
105
   bool input(uc port);
106
   bool output(uc port);
107
   bool serout(uc c);
108
 
109
   us   PC;
110
   us   SP;
111
   us   RR;
112
   us   LL;
113
   uc   opc;
114
   us   prq;
115
   us   rem;
116
   uc   imm;
117
};
118
//-----------------------------------------------------------------------------
119
bool CPU::input(uc port)
120
{
121
   switch(port)
122
      {
123
        case 0x00: RR = _getch() & 0xFF;
124
                   return false;   // serial in
125
        case 0x01: RR = 0x01;
126
                   return false;   // serial status: !TxBusy | RxRdy
127
        case 0x02: RR = 37;
128
                   return false;   // temperature
129
      }
130
 
131
   return true;   // error
132
}
133
//-----------------------------------------------------------------------------
134
bool CPU::output(uc port)
135
{
136
   switch(port)
137
      {
138
        case 0x00: return serout(RR);   ;   // serial out
139
        case 0x02: return false;
140
        case 0x03: return false;
141
        case 0x04: return false;
142
      }
143
 
144
   return true;   // error
145
}
146
//-----------------------------------------------------------------------------
147
bool CPU::serout(uc c)
148
{
149
char cc[20];
150
 
151
   if      (c == '\n')   sprintf(cc, "\n");
152
   else if (c == '\r')   sprintf(cc, "\\r");
153
   else if (c <  ' ')    sprintf(cc, "\\x%2.2X", c);
154
   else if (c > 0x7E)    sprintf(cc, "\\x%2.2X", c);
155
   else                  sprintf(cc, "%c", c);
156
 
157
   fprintf(out, "%s", cc);
158
   fprintf(log, "-> %s (0x%2.2X)\n", cc, c);
159
 
160
   return false;   // no error
161
}
162
//-----------------------------------------------------------------------------
163
int simulate()
164
{
165
CPU cpu;
166
int steps = 1;
167
 
168
   for (;;steps++)   if (cpu.Step())   return steps;
169
}
170
//-----------------------------------------------------------------------------
171
 
172
#define OP(_op, _act, _txt) case  _op:   _act   txt = _txt;   break;
173
 
174
bool CPU::Step()
175
{
176
   clock++;
177
   if (labels[PC])   fprintf(log, "%s:\n", labels[PC]);
178
 
179
const unsigned short lpc = PC;
180
const char * txt = "???";
181
bool done = false;
182
 
183
   imm = 0;
184
   opc = u8();
185
 
186
us tmp;
187
us uquick = opc & 0x0F;
188
us squick = opc & 0x0F;   if (squick & 0x08)   squick |= 0xFFF0;
189
 
190
   switch(opc)
191
      {
192
OP(0x00, { done = true;                         }, "HALT"             )
193
OP(0x01, {                                      }, "NOP"              )
194
OP(0x02, { PC = u16();                          }, "JMP  j"           )
195
OP(0x03, { tmp = u16(); if ( RR) PC = tmp;      }, "JMP  RRNZ, j"     )
196
OP(0x04, { tmp = u16(); if (!RR) PC = tmp;      }, "JMP  RRZ, j"      )
197
OP(0x05, { push16(lpc + 3);   PC = u16();       }, "CALL j"           )
198
OP(0x06, { push16(lpc + 3);   PC = RR;          }, "CALL (RR)"        )
199
OP(0x07, { PC = pop16();                        }, "RET"              )
200
OP(0x08, { RR = pop16();                        }, "MOVE (SP)+, RR"   )
201
OP(0x09, { RR = pop8s();                        }, "MOVE (SP)+, RS"   )
202
OP(0x0A, { RR = pop8u();                        }, "MOVE (SP)+, RU"   )
203
OP(0x0B, { LL = pop16();                        }, "MOVE (SP)+, LL"   )
204
OP(0x0C, { LL = pop8s();                        }, "MOVE (SP)+, LS"   )
205
OP(0x0D, { LL = pop8u();                        }, "MOVE (SP)+, LU"   )
206
OP(0x0E, { push16(RR);                          }, "MOVE RR, -(SP)"   )
207
OP(0x0F, { push8(RR);                           }, "MOVE R, -(SP)"    )
208
 
209
OP(0x10, { RR = RR & u16();                     }, "AND  RR, #u"      )
210
OP(0x11, { RR = RR & u8();                      }, "AND  RR, #u"      )
211
OP(0x12, { RR = RR | u16();                     }, "OR   RR, #u"      )
212
OP(0x13, { RR = RR | u8();                      }, "OR   RR, #u"      )
213
OP(0x14, { RR = RR ^ u16();                     }, "XOR  RR, #u"      )
214
OP(0x15, { RR = RR ^ u8();                      }, "XOR  RR, #u"      )
215
OP(0x16, { RR = yes((ss)RR == s16());           }, "SEQ  RR, #s"      )
216
OP(0x17, { RR = yes((ss)RR == s8() );           }, "SEQ  RR, #s"      )
217
OP(0x18, { RR = yes((ss)RR != s16());           }, "SNE  RR, #s"      )
218
OP(0x19, { RR = yes((ss)RR != s8() );           }, "SNE  RR, #s"      )
219
OP(0x1A, { RR = yes((ss)RR >= s16());           }, "SGE  RR, #s"      )
220
OP(0x1B, { RR = yes((ss)RR >= s8() );           }, "SGE  RR, #s"      )
221
OP(0x1C, { RR = yes((ss)RR >  s16());           }, "SGT  RR, #s"      )
222
OP(0x1D, { RR = yes((ss)RR >  s8() );           }, "SGT  RR, #s"      )
223
OP(0x1E, { RR = yes((ss)RR <= s16());           }, "SLE  RR, #s"      )
224
OP(0x1F, { RR = yes((ss)RR <= s8() );           }, "SLE  RR, #s"      )
225
 
226
OP(0x20, { RR = yes((ss)RR <  s16());           }, "SLT  RR, #s"      )
227
OP(0x21, { RR = yes((ss)RR <  s8() );           }, "SLT  RR, #s"      )
228
OP(0x22, { RR = yes((us)RR >= u16());           }, "SHS  RR, #u"      )
229
OP(0x23, { RR = yes((us)RR >= u8() );           }, "SHS  RR, #u"      )
230
OP(0x24, { RR = yes((us)RR >  u16());           }, "SHI  RR, #u"      )
231
OP(0x25, { RR = yes((us)RR >  u8() );           }, "SHI  RR, #u"      )
232
OP(0x26, { RR = yes((us)RR <= u16());           }, "SLS  RR, #u"      )
233
OP(0x27, { RR = yes((us)RR <= u8() );           }, "SLS  RR, #u"      )
234
OP(0x28, { RR = yes((us)RR <  u16());           }, "SLO  RR, #u"      )
235
OP(0x29, { RR = yes((us)RR <  u8() );           }, "SLO  RR, #u"      )
236
OP(0x2A, { SP = SP + u16();                     }, "ADD  SP, #u"      )
237
OP(0x2B, { SP = SP + u8();                      }, "ADD  SP, #u"      )
238
OP(0x2C, { push16(0);                           }, "CLRW -(SP)"       )
239
OP(0x2D, { push8(0);                            }, "CLRB -(SP)"       )
240
OP(0x2E, { done = input(u8());                  }, "IN   (u), RU"     )
241
OP(0x2F, { done = output(u8());                 }, "OUT  R, (u)"      )
242
 
243
OP(0x30, { RR = LL & RR;                        }, "AND  LL, RR"      )
244
OP(0x31, { RR = LL | RR;                        }, "OR   LL, RR"      )
245
OP(0x32, { RR = LL ^ RR;                        }, "XOR  LL, RR"      )
246
OP(0x33, { RR = yes((ss)LL == (ss)RR);          }, "SEQ  LL, RR"      )
247
OP(0x34, { RR = yes((ss)LL != (ss)RR);          }, "SNE  LL, RR"      )
248
OP(0x35, { RR = yes((ss)LL >= (ss)RR);          }, "SGE  LL, RR"      )
249
OP(0x36, { RR = yes((ss)LL >  (ss)RR);          }, "SGT  LL, RR"      )
250
OP(0x37, { RR = yes((ss)LL <= (ss)RR);          }, "SLE  LL, RR"      )
251
OP(0x38, { RR = yes((ss)LL <  (ss)RR);          }, "SLT  LL, RR"      )
252
OP(0x39, { RR = yes((us)LL >= (us)RR);          }, "SHS  LL, RR"      )
253
OP(0x3A, { RR = yes((us)LL >  (us)RR);          }, "SHI  LL, RR"      )
254
OP(0x3B, { RR = yes((us)LL <= (us)RR);          }, "SLS  LL, RR"      )
255
OP(0x3C, { RR = yes((us)LL <  (us)RR);          }, "SLO  LL, RR"      )
256
OP(0x3D, { RR = yes(! RR);                      }, "LNOT RR"          )
257
OP(0x3E, { RR = - RR;                           }, "NEG  RR"          )
258
OP(0x3F, { RR = ~ RR;                           }, "NOT  RR"          )
259
 
260
OP(0x40, { RR = LL;                             }, "MOVE LL, RR"      )
261
OP(0x41, { mem[RR] = LL; mem[RR+1] = LL>>8;     }, "MOVE LL, (RR)"    )
262
OP(0x42, { mem[RR] = LL;                        }, "MOVE L, (RR)"     )
263
OP(0x43, { LL = RR;                             }, "MOVE RR, LL"      )
264
OP(0x44, { mem[LL] = RR; mem[LL+1] = RR>>8;     }, "MOVE RR, (LL)"    )
265
OP(0x45, { mem[LL] = RR;                        }, "MOVE R, (LL)"     )
266
OP(0x46, { RR = mem16(RR);                      }, "MOVE (RR), RR"    )
267
OP(0x47, { RR = (ss)(sc)mem[RR];                }, "MOVE (RR), RS"    )
268
OP(0x48, { RR = (us)(uc)mem[RR];                }, "MOVE (RR), RU"    )
269
OP(0x49, { RR = mem16(u16());                   }, "MOVE (u), RR"     )
270
OP(0x4A, { RR = (ss)(sc)mem[u16()];             }, "MOVE (u), RS"     )
271
OP(0x4B, { RR = (us)(us)mem[u16()];             }, "MOVE (u), RU"     )
272
OP(0x4C, { LL = mem16(u16());                   }, "MOVE (u), LL"     )
273
OP(0x4D, { LL = (ss)(sc)mem[u16()];             }, "MOVE (u), LS"     )
274
OP(0x4E, { LL = (us)(us)mem[u16()];             }, "MOVE (u), LU"     )
275
OP(0x4F, { SP = RR;                             }, "MOVE RR, SP"      )
276
 
277
OP(0x52, { RR = RR       << u8();               }, "LSL  RR, #u"      )
278
OP(0x53, { RR = ((ss)RR) >> u8();               }, "ASR  RR, #u"      )
279
OP(0x54, { RR = ((us)RR) >> u8();               }, "LSR  RR, #u"      )
280
OP(0x55, { RR = LL       << RR;                 }, "LSL  LL, RR"      )
281
OP(0x56, { RR = ((ss)LL) >> RR;                 }, "ASR  LL, RR"      )
282
OP(0x57, { RR = ((us)LL) >> RR;                 }, "LSR  LL, RR"      )
283
OP(0x58, { RR = LL +  RR;                       }, "ADD  LL, RR"      )
284
OP(0x59, { RR = LL -  RR;                       }, "SUB  LL, RR"      )
285
OP(0x5A, { mem[tmp = u16()] = RR;
286
           mem[tmp + 1] = RR >> 8;              }, "MOVE  RR, (u)"    )
287
OP(0x5B, { mem[u16()] = RR;                     }, "MOVE  R, (u)"     )
288
OP(0x5C, { mem16(SP + u16(), RR);               }, "MOVE  RR, u(SP)"  )
289
OP(0x5D, { mem16(SP + u8(), RR);                }, "MOVE  RR, u(SP)"  )
290
OP(0x5E, { mem[SP + u16()] = RR;                }, "MOVE  R, u(SP)"   )
291
OP(0x5F, { mem[SP + u8()] = RR;                 }, "MOVE  R, u(SP)"   )
292
 
293
OP(0x60, { RR = mem16(SP + u16());              }, "MOVE u(SP), RR"   )
294
OP(0x61, { RR = mem16(SP + u8());               }, "MOVE u(SP), RR"   )
295
OP(0x62, { RR = (ss)(sc)mem[SP + u16()];        }, "MOVE u(SP), RS"   )
296
OP(0x63, { RR = (ss)(sc)mem[SP + u8()];         }, "MOVE u(SP), RS"   )
297
OP(0x64, { RR = (us)(uc)mem[SP + u16()];        }, "MOVE u(SP), RU"   )
298
OP(0x65, { RR = (us)(uc)mem[SP + u8()];         }, "MOVE u(SP), RU"   )
299
OP(0x66, { LL = mem16(SP + u16());              }, "MOVE u(SP), LL"   )
300
OP(0x67, { LL = mem16(SP + u8());               }, "MOVE u(SP), LL"   )
301
OP(0x68, { LL = (ss)(sc)mem[SP + u16()];        }, "MOVE u(SP), LS"   )
302
OP(0x69, { LL = (ss)(sc)mem[SP + u8() ];        }, "MOVE u(SP), LS"   )
303
OP(0x6A, { LL = (us)(uc)mem[SP + u16()];        }, "MOVE u(SP), LU"   )
304
OP(0x6B, { LL = (us)(uc)mem[SP + u8() ];        }, "MOVE u(SP), LU"   )
305
OP(0x6C, { RR = SP + u16();                     }, "LEA  u(SP), RR"   )
306
OP(0x6D, { RR = SP + u8();                      }, "LEA  u(SP), RR"   )
307
OP(0x6E, { mem[--LL] = mem[--RR];               }, "MOVE -(RR), -(LL)")
308
OP(0x6F, { mem[LL++] = mem[RR++];               }, "MOVE (RR)+, (LL)+")
309
 
310
OP(0x70, { prq = (ss)LL * (ss)RR;               }, "MUL_IS"           )
311
OP(0x71, { prq = (us)LL * (us)RR;               }, "MUL_IU"           )
312
OP(0x72, { prq = (ss)LL / (ss)RR;
313
           rem = (ss)LL % (ss)RR;               }, "DIV_IS"           )
314
OP(0x73, { prq = (us)LL / (us)RR;
315
           rem = (us)LL % (us)RR;               }, "DIV_IU"           )
316
OP(0x74, {                                      }, "MD_STP"           )
317
OP(0x75, { RR = prq;                            }, "MD_FIN"           )
318
OP(0x76, { RR = rem;                            }, "MOD_FIN"          )
319
OP(0x77, {                                      }, "EI"               )
320
OP(0x78, { PC = pop16();                        }, "RETI"             )
321
OP(0x79, {                                      }, "DI"               )
322
 
323
OP(0xA0 ... 0xAF, { RR = RR +      uquick;      }, "ADD  RR, #u"      )
324
OP(0xB0 ... 0xBF, { RR = RR -      uquick;      }, "SUB  RR, #u"      )
325
OP(0xC0 ... 0xCF, { RR =           squick;      }, "MOVE #s, RR"      )
326
OP(0xD0 ... 0xDF, { RR = yes(LL == squick);     }, "SEQ  LL, #s"      )
327
OP(0xE0 ... 0xEF, { LL =           squick;      }, "MOVE #s, LL"      )
328
 
329
OP(0xF4, { RR =  RR + u16();                    }, "ADD  RR, #u"      )
330
OP(0xF5, { RR =  RR + u8();                     }, "ADD  RU, #u"      )
331
OP(0xF6, { RR =  RR - u16();                    }, "SUB  RR, #u"      )
332
OP(0xF7, { RR =  RR - u8();                     }, "SUB  RU, #u"      )
333
OP(0xF8, { RR  =  s16();                        }, "MOVE #s, RR"      )
334
OP(0xF9, { RR  =  s8();                         }, "MOVE #s, RS"      )
335
OP(0xFA, { RR  =  yes(LL == s16());             }, "SEQ  LL, #s"      )
336
OP(0xFB, { RR  =  yes(LL == s8());              }, "SEQ  LL, #s"      )
337
OP(0xFC, { LL  =  s16();                        }, "MOVE #s, LL"      )
338
OP(0xFD, { LL  =  s8();                         }, "MOVE #s, LL"      )
339
 
340
default:   fprintf(log, "%4.4X: Bad Opcode 0x%2.2X\n", lpc, opc);
341
           txt = "???";   done = true;
342
      }
343
 
344
   if (do_log)
345
      {
346
        fprintf(log, "%4.4X    %4.4X : ", clock, lpc);
347
 
348
        fprintf(log, "%2.2X ", mem[lpc]);
349
        if      (imm == 1)   fprintf(log, "    ");
350
        else if (imm == 2)   fprintf(log, "%2.2X  ", mem[lpc + 1]);
351
        else if (imm == 3)   fprintf(log, "%2.2X%2.2X",
352
                                     mem[lpc + 2], mem[lpc + 1]);
353
        else                 assert(0);
354
 
355
        fprintf(log, "   ");
356
        print_txt(txt, imm, mem[lpc], mem[lpc + 1], mem[lpc + 2]);
357
 
358
        fprintf(log, "-> SP=%4.4X (%4.4X) ", SP, _16(mem[SP+1], mem[SP]));
359
 
360
        fprintf(log, "LL=%4.4X ", LL);
361
        fprintf(log, "RR=%4.4X\n", RR);
362
 
363
        if (PC != lpc + imm)   fprintf(log, "\n");
364
      }
365
 
366
   if (PC > 0xA000)
367
      {
368
        fprintf(log, "Bad PC %d\n", PC);
369
        fclose(log);
370
        assert(0 && "Bad PC");
371
      }
372
 
373
   if (SP > 0xA000)
374
      {
375
        fprintf(log, "Bad SP %d\n", SP);
376
        fclose(log);
377
        assert(0 && "Bad SP");
378
      }
379
 
380
   return done;
381
}
382
//-----------------------------------------------------------------------------
383
void print_txt(const char * txt, int imm, us op, us l, us h)
384
{
385
int len = 0;
386
us hl = (h << 8) | l;
387
 
388
   for (; *txt; txt++)
389
       {
390
         if (*txt == 'u')
391
            {
392
              if      (imm == 1)   len += fprintf(log, "%d", op & 0x0F);
393
              else if (imm == 2)   len += fprintf(log, "%d", l);
394
              else if (imm == 3)   len += fprintf(log, "%d", hl);
395
              else                 assert(0);
396
            }
397
         else if (*txt == 's')
398
            {
399
              if      (imm == 1)
400
                 {
401
 
402
                   if (imm & 0x08)   len += fprintf(log, "%d", op | 0xFFFFFFF8);
403
                   else              len += fprintf(log, "%d", op & 0x00000007);
404
                 }
405
              else if (imm == 2)
406
                 {
407
                   if (imm & 0x80)   len += fprintf(log, "%d", l | 0xFFFFFF80);
408
                   else              len += fprintf(log, "%d", l & 0x0000007F);
409
                 }
410
              else if (imm == 3)   len += fprintf(log, "%d", (ss)hl);
411
              else                 assert(0);
412
            }
413
         else if (*txt == 'j')
414
            {
415
              if (labels[hl])   len += fprintf(log, "%s", labels[hl]);
416
              else              len += fprintf(log, "%X", hl);
417
            }
418
         else                    len += fprintf(log, "%c", *txt);
419
       }
420
 
421
   while (len < 28)   len += fprintf(log, " ");
422
}
423
//-----------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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