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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [sim/] [cpp/] [zsim.cpp] - Blame information for rev 204

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

Line No. Rev Author Line
1 204 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    zsim.cpp
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
6
//
7
// Purpose:     The main portion of a Simulator, not based upon any RTL or
8
//              Verilog code.  Why?  To get something up and running and testing
9
//      faster (even though the Verilog should be working/running?).
10
//
11
//
12
// Creator:     Dan Gisselquist, Ph.D.
13
//              Gisselquist Technology, LLC
14
//
15
////////////////////////////////////////////////////////////////////////////////
16
//
17
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
18
//
19
// This program is free software (firmware): you can redistribute it and/or
20
// modify it under the terms of  the GNU General Public License as published
21
// by the Free Software Foundation, either version 3 of the License, or (at
22
// your option) any later version.
23
//
24
// This program is distributed in the hope that it will be useful, but WITHOUT
25
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
26
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
27
// for more details.
28
//
29
// License:     GPL, v3, as defined and found on www.gnu.org,
30
//              http://www.gnu.org/licenses/gpl.html
31
//
32
//
33
////////////////////////////////////////////////////////////////////////////////
34
//
35
//
36
#include <stdio.h>
37
#include <stdint.h>
38
#include <stdlib.h>
39
#include <unistd.h>
40
#include <assert.h>
41
#include <string.h>
42
#include <vector>
43
#include <ctype.h>
44
#include "twoc.h"
45
#include "zipelf.h"
46
 
47
#define CC_CLRCACHE     (1<<14)
48
#define CC_PHASE_BIT    (1<<13)
49
#define CC_PHASE        (1<<13)
50
#define CC_FPUERR       (1<<12)
51
#define CC_DIVERR       (1<<11)
52
#define CC_BUSERR       (1<<10)
53
#define CC_TRAP         (1<<9)
54
#define CC_ILL          (1<<8)
55
#define CC_BREAK        (1<<7)
56
#define CC_STEP         (1<<6)
57
#define CC_GIE          (1<<5)
58
#define CC_SLEEP        (1<<4)
59
#define CC_V            (1<<3)
60
#define CC_N            (1<<2)
61
#define CC_C            (1<<1)
62
#define CC_Z            (1   )
63
 
64
class   SIMDEV {
65
public:
66
        virtual uint32_t        lw(uint32_t addr) = 0;
67
        virtual void    sw(uint32_t addr, uint32_t vl) = 0;
68
 
69
        virtual uint32_t        lb(uint32_t addr) {
70
                uint32_t v = lw(addr&-4);
71
 
72
                // fprintf(stderr, "\tLH(%08x) -> %08x", addr, v);
73
                v >>= (8*(3-(addr&3)));
74
                // fprintf(stderr, " -> %08x", v);
75
                v &= 0x0ff;
76
                // fprintf(stderr, " -> %02x\n", v);
77
                return v;
78
        }
79
        virtual uint32_t        lh(uint32_t addr) {
80
                uint32_t v = lw(addr&-4);
81
 
82
                // fprintf(stderr, "\tLH(%08x) -> %08x", addr, v);
83
                if ((addr&2)==0)
84
                        v >>= 16;
85
                // fprintf(stderr, " -> %08x", v);
86
                v &= 0x0ffff;
87
                // fprintf(stderr, " -> %04x\n", v);
88
                return v;
89
        }
90
 
91
        virtual void sh(uint32_t addr, uint32_t vl) {
92
                uint32_t v = (vl & 0x0ffff);
93
                v = v | (v<<16);
94
                sw(addr, v);
95
        }
96
 
97
        virtual void sb(uint32_t addr, uint32_t vl) {
98
                uint32_t v = (vl & 0x0ff);
99
                v = v | (v<<16);
100
                v = v | (v<<8);
101
                sw(addr, v);
102
        }
103
 
104
        virtual bool    interrupt(void) { return false; };
105
        virtual void    tick(void) {};
106
 
107
        virtual void    load(uint32_t addr, const char *buf, size_t ln) {}
108
};
109
 
110
class   UARTDEV : public SIMDEV {
111
        uint32_t        m_setup;
112
        bool            m_debug;
113
public:
114
        UARTDEV(void) { m_setup = 868; m_debug = false; }
115
 
116
        virtual uint32_t        lw(uint32_t addr) {
117
                switch(addr&0x0c) {
118
                case  0: return m_setup;
119
                case  4: return 0;
120
                case  8: return 0x100;
121
                case 12: return 0;
122
                } return 0;
123
        }
124
 
125
        virtual void sw(uint32_t addr, uint32_t vl) {
126
                if (m_debug) fprintf(stderr,
127
                        "UART->SW(%08x, %08x)\n", addr, vl);
128
                switch(addr&0x0c) {
129
                case  0: m_setup = vl & 0x3fffffff; break;
130
                case  4: break;
131
                case  8: break;
132
                case 12: putchar(vl & 0x0ff);
133
                }
134
        }
135
};
136
 
137
 
138
class   MEMDEV : public SIMDEV {
139
protected:
140
        char    *m_mem;
141
        bool    m_dbg;
142
public:
143
        MEMDEV(int nbits) {
144
                m_mem = new char[(1<<nbits)];
145
                m_dbg = false;
146
        }
147
 
148
        virtual uint32_t        lw(uint32_t addr) {
149
                unsigned char   a, b, c, d;
150
                uint32_t        v;
151
 
152
                a = m_mem[addr];
153
                b = m_mem[addr+1];
154
                c = m_mem[addr+2];
155
                d = m_mem[addr+3];
156
                v = (a<<24)|(b<<16)|(c<<8)|d;
157
 
158
                if (m_dbg) fprintf(stderr,
159
                        "\tReading %08x -> %02x:%02x:%02x:%02x -> v=%08x\n", addr,
160
                        a, b, c, d, v);
161
 
162
                return v;
163
        }
164
 
165
        virtual void sw(uint32_t addr, uint32_t vl) {
166
                uint32_t maddr = addr & -4;
167
                m_mem[(maddr)  ] = (vl >>24)&0x0ff;
168
                m_mem[(maddr)+1] = (vl >>16)&0x0ff;
169
                m_mem[(maddr)+2] = (vl >> 8)&0x0ff;
170
                m_mem[(maddr)+3] = (vl     )&0x0ff;
171
 
172
                if (m_dbg)
173
                        fprintf(stderr,
174
                                "\tSW %08x <- %08x - %02x:%02x:%02x:%02x\n",
175
                                addr, vl, m_mem[(maddr)  ] & 0x0ff,
176
                                m_mem[(maddr)+1] & 0x0ff,
177
                                m_mem[(maddr)+2] & 0x0ff,
178
                                m_mem[(maddr)+3] & 0x0ff);
179
        }
180
 
181
        virtual void sh(uint32_t addr, uint32_t vl) {
182
                uint32_t maddr = addr & -2;
183
                m_mem[(maddr)  ] = (vl >> 8)&0x0ff;
184
                m_mem[(maddr)+1] = (vl     )&0x0ff;
185
                if (m_dbg)
186
                        fprintf(stderr, "\tSH %08x <- %04x - %02x:%02x\n",
187
                                addr, vl & 0x0ffff, m_mem[(maddr)  ] & 0x0ff,
188
                                m_mem[(maddr)+1] & 0x0ff);
189
        }
190
 
191
        virtual void sb(uint32_t addr, uint32_t vl) {
192
                m_mem[addr] = vl;
193
                if (m_dbg)
194
                        fprintf(stderr, "\tSB %08x <- %02x\n",
195
                                addr, vl & 0x0ff);
196
        }
197
 
198
        void    load(uint32_t addr, const char *src, size_t n) {
199
                memcpy(&m_mem[addr], src, n);
200
        }
201
};
202
 
203
class   ROMDEV : public MEMDEV {
204
public:
205
        ROMDEV(int nbits) : MEMDEV(nbits) {}
206
 
207
        // virtual      uint32_t        lw(uint32_t addr);
208
        virtual void    sw(uint32_t addr, uint32_t vl) {}
209
        virtual void    sh(uint32_t addr, uint32_t vl) {}
210
        virtual void    sb(uint32_t addr, uint32_t vl) {}
211
        void    load(uint32_t addr, const char *src, size_t n) {
212
                memcpy(&m_mem[addr], src, n);
213
        }
214
};
215
 
216
#ifndef L_OK
217
#define L_OK    8       // Okay for loads
218
#endif
219
 
220
class   SIMENTRY {
221
public:
222
        SIMDEV  *m_dev;
223
        uint32_t m_addr, m_mask;
224
        int     m_flags;
225
        char    *m_name;
226
};
227
 
228
class   SIMBUS {
229
        bool    m_buserr;
230
        std::vector<SIMENTRY *> m_devlist;
231
        int     getdev(uint32_t addr) {
232
                for(size_t i=0; i<m_devlist.size(); i++)
233
                        if ((addr&m_devlist[i]->m_mask)==m_devlist[i]->m_addr){
234
                                return i;
235
                }
236
 
237
                /*
238
                fprintf(stderr, "GETDEV(0x%08x) - not found\n", addr);
239
                for(size_t i=0; i<m_devlist.size(); i++) {
240
                        fprintf(stderr, "ADDR(0x%08x) & 0x%08x = %08x != %08x\n",
241
                                addr, m_devlist[i]->m_mask,
242
                                addr & m_devlist[i]->m_mask,
243
                                m_devlist[i]->m_addr);
244
                } */
245
 
246
                return -1;
247
        }
248
        int     getwrdev(uint32_t addr) {
249
                int     devid = getdev(addr);
250
                if (0 <= devid) {
251
                        if (m_devlist[devid]->m_flags & W_OK)
252
                                return devid;
253
fprintf(stderr, "ADDRESS %08x in %s is not writable!!\n", addr, m_devlist[devid]->m_name);
254
                }
255
else fprintf(stderr, "ADDRESS %08x not found\n", addr);
256
                return -1;
257
        }
258
        int     getexdev(uint32_t addr) {
259
                int     devid = getdev(addr);
260
                if (0 <= devid) {
261
                        if (m_devlist[devid]->m_flags & X_OK)
262
                                return devid;
263
                        fprintf(stderr, "Address in %s is not executable\n", m_devlist[devid]->m_name);
264
                }
265
                fprintf(stderr, "ExDEV not found (0x%08x), devid = %d\n", addr, devid);
266
                return -1;
267
        }
268
public:
269
        SIMBUS(void) { m_buserr = false; }
270
        void    add(SIMDEV *dev, uint32_t addr, uint32_t mask, const char *p, const char *name = "") {
271
                SIMENTRY        *s = new SIMENTRY;
272
 
273
                s->m_dev = dev;
274
                s->m_addr= addr;
275
                s->m_mask= mask;
276
                s->m_name= strdup(name);
277
                s->m_flags= 0;
278
 
279
                if ((strchr(p, 'w'))||(strchr(p, 'W')))
280
                        s->m_flags |= W_OK;
281
                if ((strchr(p, 'r'))||(strchr(p, 'R')))
282
                        s->m_flags |= R_OK;
283
                if ((strchr(p, 'x'))||(strchr(p, 'X')))
284
                        s->m_flags |= X_OK;
285
                if ((strchr(p, 'l'))||(strchr(p, 'L')))
286
                        s->m_flags |= L_OK;
287
                m_devlist.push_back(s);
288
        }
289
 
290
        uint32_t        lb(uint32_t addr) {
291
                int     devid;
292
                if (0 <= (devid = getdev(addr)))
293
                        return m_devlist[devid]->m_dev->lb(addr & (~m_devlist[devid]->m_mask));
294
                m_buserr = true;
295
                return 0;
296
        }
297
        uint32_t        lh(uint32_t addr) {
298
                int     devid;
299
                if (0 <= (devid = getdev(addr)))
300
                        return m_devlist[devid]->m_dev->lh(addr & ((~m_devlist[devid]->m_mask)&-2));
301
                m_buserr = true;
302
                return 0;
303
        }
304
        uint32_t        lw(uint32_t addr) {
305
                int     devid;
306
                if (0 <= (devid = getdev(addr)))
307
                        return m_devlist[devid]->m_dev->lw(addr & ((~m_devlist[devid]->m_mask)&-4));
308
                m_buserr = true;
309
                return 0;
310
        }
311
        uint32_t        lx(uint32_t addr) {
312
                int     devid;
313
                if (0 <= (devid = getexdev(addr)))
314
                        return m_devlist[devid]->m_dev->lw(addr & ((~m_devlist[devid]->m_mask)&-4));
315
                m_buserr = true;
316
                return 0;
317
        }
318
        void    sb(uint32_t addr, uint32_t vl) {
319
                int     devid;
320
                if (0 <= (devid = getwrdev(addr))) {
321
                        return m_devlist[devid]->m_dev->sb(addr & (~m_devlist[devid]->m_mask), vl & 0x0ff);
322
                } else {
323
                        fprintf(stderr, "No such address, %08x\n", addr);
324
                }
325
                m_buserr = true;
326
                return;
327
        }
328
        void    sh(uint32_t addr, uint32_t vl) {
329
                int     devid;
330
                if (0 <= (devid = getwrdev(addr)))
331
                        return m_devlist[devid]->m_dev->sh(addr & -2 & (~m_devlist[devid]->m_mask), vl & 0x0ffff);
332
                m_buserr = true;
333
                return;
334
        }
335
        void    sw(uint32_t addr, uint32_t vl) {
336
                int     devid;
337
                if (0 <= (devid = getwrdev(addr)))
338
                        return m_devlist[devid]->m_dev->sw(addr & -4 & (~m_devlist[devid]->m_mask), vl);
339
                m_buserr = true;
340
                return;
341
        }
342
        bool    interrupt(void) { return false; };
343
 
344
        bool    error(void) {
345
                bool tmp = m_buserr;
346
                m_buserr = false;
347
                return tmp;
348
        }
349
 
350
        void    tick(void) {
351
                for(size_t i=0; i<m_devlist.size(); i++)
352
                        m_devlist[i]->m_dev->tick();
353
        }
354
 
355
        void    load(uint32_t addr, const char *data, size_t len) {
356
                int     devid;
357
                if ((0 <= (devid = getdev(addr)))
358
                                &&(m_devlist[devid]->m_flags & L_OK))
359
                        m_devlist[devid]->m_dev->load(
360
                                addr & (~m_devlist[devid]->m_mask), data, len);
361
                else {
362
                        fprintf(stderr, "DEVID = %d\n", devid);
363
                        m_buserr = true;
364
                } return;
365
        }
366
};
367
 
368
class   ZIPMACHINE {
369
        bool            m_gie, m_jumped, m_advance_pc, m_locked;
370
        int             m_lockcount;
371
        unsigned long   m_icount;
372
public:
373
        uint32_t        m_r[32];
374
        SIMBUS          *m_bus;
375
        FILE            *m_mapf;
376
 
377
        ZIPMACHINE(void) {
378
                m_locked = false; m_lockcount = 0;
379
                m_mapf = NULL;
380
                m_bus = NULL;
381
                m_gie = false;
382
                m_jumped= m_advance_pc = false;
383
                m_icount = 0;
384
        }
385
 
386
        void dump() {
387
                fflush(stderr);
388
                fflush(stdout);
389
                printf("ZIPM--DUMP: ");
390
                if (gie())
391
                        printf("Interrupts-enabled\n");
392
                else
393
                        printf("Supervisor mode\n");
394
                printf("\n");
395
 
396
                printf("sR0 : %08x ", m_r[0]);
397
                printf("sR1 : %08x ", m_r[1]);
398
                printf("sR2 : %08x ", m_r[2]);
399
                printf("sR3 : %08x\n",m_r[3]);
400
                printf("sR4 : %08x ", m_r[4]);
401
                printf("sR5 : %08x ", m_r[5]);
402
                printf("sR6 : %08x ", m_r[6]);
403
                printf("sR7 : %08x\n",m_r[7]);
404
                printf("sR8 : %08x ", m_r[8]);
405
                printf("sR9 : %08x ", m_r[9]);
406
                printf("sR10: %08x ", m_r[10]);
407
                printf("sR11: %08x\n",m_r[11]);
408
                printf("sR12: %08x ", m_r[12]);
409
                printf("sSP : %08x ", m_r[13]);
410
                printf("sCC : %08x ",(m_r[14] & (~CC_GIE)));
411
                printf("sPC : %08x\n",m_r[15]);
412
 
413
                printf("\n");
414
 
415
                printf("uR0 : %08x ", m_r[16]);
416
                printf("uR1 : %08x ", m_r[17]);
417
                printf("uR2 : %08x ", m_r[18]);
418
                printf("uR3 : %08x\n",m_r[19]);
419
                printf("uR4 : %08x ", m_r[20]);
420
                printf("uR5 : %08x ", m_r[21]);
421
                printf("uR6 : %08x ", m_r[22]);
422
                printf("uR7 : %08x\n",m_r[23]);
423
                printf("uR8 : %08x ", m_r[24]);
424
                printf("uR9 : %08x ", m_r[25]);
425
                printf("uR10: %08x ", m_r[26]);
426
                printf("uR11: %08x\n",m_r[27]);
427
                printf("uR12: %08x ", m_r[28]);
428
                printf("uSP : %08x ", m_r[29]);
429
                printf("uCC : %08x ",(m_r[30]|CC_GIE));
430
                printf("uPC : %08x\n",m_r[31]);
431
                printf("\n");
432
                fflush(stderr);
433
                fflush(stdout);
434
        }
435
 
436
        void    ccodes(uint32_t newflags) {
437
                m_r[14+rbase()] = (cc() & -16)|(newflags&0x0f);
438
        }
439
 
440
        int     rbase(void) { return m_gie?16:0; }
441
        bool    gie()           { return m_gie; };
442
        bool    locked()        { return m_locked; };
443
        bool    sleeping()      {
444
                return (gie())&&(m_r[14+16]&CC_SLEEP)?true:false;
445
        };
446
        bool    sleep(bool nv)  {
447
                if (nv) {
448
                        m_r[14   ] |= CC_SLEEP;
449
                        m_r[14+16] |= CC_SLEEP;
450
                } else {
451
                        m_r[14   ] &= (~CC_SLEEP);
452
                        m_r[14+16] &= (~CC_SLEEP);
453
                } return sleeping();
454
        };
455
        bool    halted()        {
456
                return (!gie()) && (m_r[14]&CC_SLEEP);
457
        };
458
        uint32_t        cc()    { return m_r[14+rbase()]|((m_gie)?CC_GIE:0); };
459
        bool    fault()         {
460
                if (cc() & (CC_PHASE|CC_ILL|CC_BREAK|CC_BUSERR|CC_DIVERR))
461
                        return true;
462
                return false;
463
        }
464
        bool    gie(bool v)     {
465
                m_jumped = (m_gie != v);
466
                m_gie = v;
467
                return v;
468
        }
469
        bool    jumped(void)    { return m_jumped; };
470
        void    pc_advance(bool pcgie) {
471
                m_r[15+((pcgie)?16:0)] += 4;
472
                m_r[15+((pcgie)?16:0)] &= -4;
473
        } void  pc_advance(void) { pc_advance(gie()); }
474
        uint32_t        pc(void)        {
475
                return m_r[15+rbase()];
476
        }
477
 
478
        static uint32_t bitreverse(uint32_t bv) {
479
                uint32_t b, r=0;
480
                for(b=0; b<32; b++, bv>>=1)
481
                        r = (r<<1)|(bv&1);
482
                return r;
483
        }
484
 
485
        void    init(SIMBUS *bus) {
486
                m_bus = bus;
487
                for(int i=0; i<32; i++)
488
                        m_r[i] = 0;
489
                m_gie = false;
490
        }
491
 
492
        void    siminsn(uint32_t insn) {
493
                // fprintf(stderr, "SIM-INSN(0x%08x)\n", insn);
494
                if ((insn & 0x0fffff)==0x00100) {
495
                        // SIM Exit(0)
496
                        exit(0);
497
                } else if ((insn & 0x0ffff0)==0x00310) {
498
                        // SIM Exit(User-Reg)
499
                        int     rcode;
500
                        rcode = m_r[(insn&0x0f)+16] & 0x0ff;
501
                        exit(rcode);
502
                } else if ((insn & 0x0ffff0)==0x00300) {
503
                        // SIM Exit(Reg)
504
                        int     rcode;
505
                        rcode = m_r[(insn&0x0f)+rbase()] & 0x0ff;
506
                        exit(rcode);
507
                } else if ((insn & 0x0fff00)==0x00100) {
508
                        // SIM Exit(Imm)
509
                        int     rcode;
510
                        rcode = insn & 0x0ff;
511
                        exit(rcode);
512
                } else if ((insn & 0x0fffff)==0x002ff) {
513
                        // Full/unconditional dump
514
                        fprintf(stderr, "SIM-DUMP\n");
515
                        dump();
516
                } else if ((insn & 0x0ffff0)==0x00200) {
517
                        // Dump a register
518
                        int rid = (insn&0x0f)+rbase();
519
                        fprintf(stderr, "R[%2d] = 0x%08x\n", rid, m_r[rid]);
520
                } else if ((insn & 0x0ffff0)==0x00210) {
521
                        // Dump a user register
522
                        int rid = (insn&0x0f);
523
                        fprintf(stderr, "uR[%2d] = 0x%08x\n", rid, m_r[rid+16]);
524
                } else if ((insn & 0x0ffff0)==0x00230) {
525
                        // SOUT[User Reg]
526
                        int rid = (insn&0x0f)+16;
527
                        fprintf(stderr, "%c", m_r[rid]&0x0ff);
528
                } else if ((insn & 0x0fffe0)==0x00220) {
529
                        // SOUT[User Reg]
530
                        int rid = (insn&0x0f)+rbase();
531
                        fprintf(stderr, "%c", m_r[rid]&0x0ff);
532
                } else if ((insn & 0x0fff00)==0x00400) {
533
                        // SOUT[Imm]
534
                        fprintf(stderr, "%c", insn&0x0ff);
535
                } else { // if ((insn & 0x0f7c00000)==0x77800000)
536
                        uint32_t        imm = insn & 0x03fffff;
537
                        // Simm instruction that we dont recognize
538
                        // if (imm)
539
                        fprintf(stderr, "SIM 0x%08x\n", imm);
540
                }
541
        }
542
 
543
        void    fullinsn(uint32_t insn) {
544
                bool    wf, wb, fpu, noop, lock, wbreak, cmptst, mem,
545
                        sto, ldi, mov, div, execinsn;
546
                bool    diverr, illegal;
547
                uint32_t        av, bv, result, f, arg, brg, opc;
548
                int32_t         imm;
549
                int             rb, cnd;
550
                const bool      dbg = false;
551
 
552
                m_icount ++ ;
553
 
554
                if (dbg) {
555
                        fprintf(stderr, "%8ld INSN(@0x%08x, %08x)", m_icount, pc(), insn);
556
                        if (m_mapf) {
557
                                // bool dbg = pc() == 0x040003cc;
558
                                char    line[512], needle[512], *ptr = NULL,*lp;
559
                                sprintf(needle, "%08x", pc());
560
                                rewind(m_mapf);
561
                                while(NULL != (lp = fgets(line, sizeof(line), m_mapf))) {
562
                                        while((*lp)&&(isspace(*lp)))
563
                                                lp++;
564
                                        if ((*lp != '0')||(tolower(*lp) == 'x'))
565
                                                continue;
566
                                        // if (dbg)fprintf(stderr, "\tMAP (%s?) %s\n", needle, lp);
567
                                        if (NULL != (ptr = strstr(lp, needle))){
568
                                                break;
569
                                        }
570
                                } if (ptr) {
571
                                        if (strlen(ptr) > 8)
572
                                                ptr += 8;
573
                                        while((*ptr)&&(isspace(*ptr)))
574
                                                ptr++;
575
                                        int ln = strlen(ptr);
576
                                        while((ln > 0)&&(isspace(ptr[ln-1])))
577
                                                ptr[--ln] = '\0';
578
                                        fprintf(stderr, "\t%s", ptr);
579
                                } else if (0x7b400000 == (insn&0x7fffffff))
580
                                        fprintf(stderr, "\treturn");
581
                        } else fprintf(stderr, "\tNO-MAPF");
582
                        fprintf(stderr, "\n");
583
                }
584
                m_jumped     = false;
585
                m_advance_pc = true;
586
                illegal      = false;
587
                noop         = false;
588
                lock         = false;
589
                wbreak       = false;
590
 
591
                if (m_locked) {
592
                        m_lockcount--;
593
                        if (m_lockcount <= 0)
594
                                m_locked = false;
595
                }
596
 
597
                m_r[14+rbase()]
598
                        &= ~(CC_ILL|CC_BREAK|CC_BUSERR|CC_DIVERR);
599
 
600
                opc = (insn >> 22) & 0x01f;
601
                arg = (insn >> 27) & 0x0f;
602
                brg = (insn >> 14) & 0x0f;
603
 
604
                cmptst=((opc&0x1e)==0x010);
605
                mem = ((opc&0x1c) == 0x014)||((opc&0x1e) == 0x012);
606
                sto = (mem)&&(opc&1);
607
                fpu =(((opc&0x1c)==0x1c)                // Top four FPU ops
608
                                ||((opc&0x1e)==0x1a));  // Bottom two FPU ops
609
                div =((opc&0x1e)==0x0e);
610
                ldi =((opc&0x1e)==0x18);
611
                mov =((opc&0x1f)==0x0d);
612
 
613
                if (ldi)        imm = sbits(insn, 23);
614
                else if (mov)   imm = sbits(insn, 13);
615
                else if (insn & 0x040000)
616
                                imm = sbits(insn, 14);
617
                else            imm = sbits(insn, 18);
618
 
619
                // Do we read the B register?
620
                rb = (mov)||(((insn>>18)&1)&&(!ldi));
621
 
622
                // WriteBack
623
                wb = (!cmptst)&&(!sto);
624
 
625
                // Do we write flags back?
626
                wf = true;
627
                if (ldi)        wf = false;
628
                if (mov)        wf = false;
629
                if (mem)        wf = false;
630
                if (opc==0x08)  wf = false;     // BREV
631
                if (opc==0x09)  wf = false;     // LDILO
632
                if ((!cmptst)&&((arg & 0x0e)==0x0e)) // Writes to CC or PC
633
                        wf = false;             // dont set the flags.
634
 
635
                cnd = (ldi) ? 0 : ((insn >> 19) & 7);
636
 
637
                if (fpu & ((arg&0x0e)==0x0e)) {
638
                        fpu = false;
639
                        noop  = ((opc&0x1e) == 0x1e);
640
                        lock  = ((opc&0x1f) == 0x1d);
641
                        wbreak = ((opc&0x1f) == 0x1c);
642
                        illegal = !(noop|lock|wbreak);
643
                        wb     = false;
644
                        wf     = false;
645
                        cnd    = 0;
646
                } else if (div & ((arg&0x0e)==0x0e)) {
647
                        illegal = true;
648
                }
649
 
650
                if (cnd != 0) {
651
                        if (!cmptst)
652
                                wf = false;
653
                        int     ccodes = cc() & 0x0f;
654
                        switch(cnd) {
655
                        case 1: execinsn =  (ccodes & CC_Z); break;
656
                        case 2: execinsn =  (ccodes & CC_N); break;
657
                        case 3: execinsn =  (ccodes & CC_C); break;
658
                        case 4: execinsn =  (ccodes & CC_V); break;
659
                        case 5: execinsn = ((ccodes & CC_Z)==0); break;  // NZ
660
                        case 6: execinsn = ((ccodes & CC_N)==0); break;  // GE
661
                        case 7: execinsn = ((ccodes & CC_C)==0); break;  // NC
662
                        default:        execinsn = true;        break;
663
                        }
664
                } else
665
                        execinsn = true;
666
 
667
                if ((mov)&&(!gie())) {
668
                        // Supervisor can read all registers
669
                        arg |= (insn&0x40000)?0x10:0;
670
                        brg |= (insn&0x02000)?0x10:0;
671
                } else {
672
                        arg |= (gie())?0x10:0;
673
                        brg |= (gie())?0x10:0;
674
                }
675
                result = 0;
676
 
677
                bv = imm;
678
                if (rb) {
679
                        if ((brg&0x0f)==15) { // PC 
680
                                bv = (imm << 2) + m_r[brg];
681
                                if (gie()) {
682
                                        if (brg & 0x010)
683
                                                bv += 4;
684
                                } else if ((brg & 0x10)==0)
685
                                        bv += 4;
686
                        } else
687
                                bv += m_r[brg];
688
                }
689
                av = m_r[arg];
690
                if ((int)arg == 15 + rbase())
691
                        av += 4;
692
 
693
                if (execinsn) {
694
                        f = 0;   // Resulting flags
695
                        if (fpu) {
696
                                float   fva, fvb, fvr;
697
                                fva = *(float *)&av;
698
                                fvb = *(float *)&bv;
699
 
700
                                switch(opc) {
701
                                case 26: fvr = fva + fvb;       break;
702
                                case 27: fvr = fva - fvb;       break;
703
                                case 28: fvr = fva * fvb;       break;
704
                                case 29: fvr = fva / fvb;       break;
705
                                case 30: fvr = (float)bv;       break;
706
                                case 31: result = (int)fvb;     break;
707
                                default: illegal = true;
708
                                } if (opc != 31)
709
                                        result = *(uint32_t *)&fvr;
710
                                if (result == 0)
711
                                        f = CC_Z;
712
                                if (opc == 31) {
713
                                        if (result & 0x80000000)
714
                                                f |= CC_N;
715
                                } else if (fvr < 0.0)
716
                                        f |= CC_N;
717
                        } else if (noop) {
718
                                if (insn != 0x7fc00000)
719
                                        siminsn(insn);
720
                        } else if (wbreak) {
721
                                wf = wb = false;
722
                                m_advance_pc = false;
723
                                if (gie()) {
724
                                        m_r[16+14] &= CC_BREAK;
725
                                        gie(false);
726
                                } else {
727
                                        fprintf(stderr, "BREAK!\n");
728
                                        dump();
729
                                        exit(EXIT_FAILURE);
730
                                }
731
                        } else if (lock) {
732
                                m_locked = true;
733
                                m_lockcount = 3;
734
                        } else {
735
                                uint32_t        presign = (av>>31)&1, nsgn;
736
                                switch(opc) {
737
                                case  0: case 16: { // SUB, or CMP
738
                                        result = av - bv;
739
                                        if (av < bv)
740
                                                f |= CC_C;
741
                                        nsgn = (result >> 31)&1;
742
                                        if (presign != nsgn)
743
                                                f |= CC_V;
744
                                        } break;
745
                                case  1: case 17: result = bv & av; break;//AND or TST
746
                                case  2: { // ADD
747
                                        result = bv + av;
748
                                        if (result<(uint64_t)bv+(uint64_t)av)
749
                                                f |= CC_C;
750
                                        nsgn = (result >> 31)&1;
751
                                        if (presign != nsgn)
752
                                                f |= CC_V;
753
                                        } break;
754
                                case  3: result = bv | av; break; // OR
755
                                case  4: result = bv ^ av; break; // XOR
756
                                case  5: { // LSR
757
                                        uint32_t nsgn;
758
                                        if (bv >= 32)
759
                                                result = 0;
760
                                        else
761
                                                result = ((uint32_t)av >> bv);
762
                                        nsgn = (result >> 31)&1;
763
                                        if (presign != nsgn)
764
                                                f |= CC_V;
765
 
766
                                        if ((bv !=0)&&(bv<33)&&(av&(1<<(bv-1))))
767
                                                f |= CC_C;
768
                                        } break;
769
                                case  6: { // LSL
770
                                        uint32_t nsgn;
771
                                        if (bv >= 32)
772
                                                result = 0;
773
                                        else
774
                                                result = av << bv;
775
                                        nsgn = (result >> 31)&1;
776
                                        if (presign != nsgn)
777
                                                f |= CC_V;
778
                                        if((bv !=0)&&(bv<33)&&(av&(1<<(33-bv))))
779
                                                f |= CC_C;
780
                                        } break;
781
                                case  7: { // ASR
782
                                        if ((bv >= 32)&&(av & 0x80000000))
783
                                                result = -1;
784
                                        else if (bv >= 32)
785
                                                result = 0;
786
                                        else
787
                                                result = ((int)av >> bv);
788
 
789
                                        if (av & 0x80000000) {
790
                                                // Signed carry
791
                                                if (bv >= 31)
792
                                                        f |= CC_C;
793
                                                else if((bv != 0)
794
                                                        &&(av&(1<<(33-bv))))
795
                                                        f |= CC_C;
796
                                        } else {
797
                                                // Unsigned carry
798
                                                if((bv !=0)&&(bv<32)
799
                                                        &&(av&(1<<(33-bv))))
800
                                                        f |= CC_C;
801
                                        }
802
                                        } break;
803
                                case  8: result = bitreverse(bv);       break; // BREV
804
                                case  9: result = (av&0xffff0000)|(bv&0x0ffff); break; // LDILO
805
                                case 10: { // MPYUHI
806
                                        uint64_t ulv = av * bv;
807
                                        result = (ulv >> 32);
808
                                        } break;
809
                                case 11: { // MPYSHI
810
                                        int64_t lv = av * bv;
811
                                        result = (lv >> 32);
812
                                        } break;
813
                                case 12: { // MPY
814
                                        int64_t ulv = av * bv;
815
                                        // bool sn = (av<0)^(bv<0);
816
                                        result = (int32_t)(ulv & 0x0ffffffff);
817
                                        //if (((result&0x80000000)?1:0)
818
                                        //              ^ ((sn)?1:0))
819
                                        //      f |= CC_V;
820
                                        } break;
821
                                case 13: result = bv;           break; // MOV
822
                                case 14: { // DIVU
823
                                        if (bv == 0)
824
                                                diverr = true;
825
                                        else
826
                                                result = (uint32_t)av
827
                                                        / (uint32_t)bv;
828
                                        } break;
829
                                case 15: { // DIVS
830
                                        if (bv == 0)
831
                                                diverr = true;
832
                                        else
833
                                                result =(int32_t)av/(int32_t)bv;
834
                                        } break;
835
                                // case 16: result = av - bv;   break;
836
                                // case 17: result = av & bv;   break;
837
                                case 18: result = m_bus->lw(bv);
838
                                        break;// LW
839
                                case 19:
840
                                        m_bus->sw(bv, av);      break;// SW
841
                                case 20: result = m_bus->lh(bv);break;// LH
842
                                case 21: m_bus->sh(bv, av);     break;// SH
843
                                case 22: result = m_bus->lb(bv);break;// LB
844
                                case 23: m_bus->sb(bv, av);     break;// SB
845
                                case 24: result = bv;           break;// LDI
846
                                case 25: result = bv;           break;// LDI
847
                                default: illegal = true;
848
                                }
849
                                if (result == 0)
850
                                        f |= CC_Z;
851
                                if (result & 0x80000000)
852
                                        f |= CC_N;
853
                        }
854
 
855
                        if (illegal) {
856
                                if (gie()) {
857
                                        m_r[16+14] |= CC_ILL;
858
                                        gie(false);
859
                                        m_jumped = true;
860
                                        m_advance_pc = false;
861
                                } else {
862
                                        m_r[14] |= CC_ILL;
863
                                        fprintf(stderr, "ILLegal Instruction Exception\n");
864
                                        dump();
865
                                        exit(EXIT_FAILURE);
866
                                }
867
                        } else if ((mem)&&(m_bus->error())) {
868
                                if (gie()) {
869
                                        m_r[16+14] |= CC_BUSERR;
870
                                        gie(false);
871
                                        m_jumped = true;
872
                                        m_advance_pc = false;
873
                                } else {
874
                                        m_r[14] |= CC_BUSERR;
875
                                        fprintf(stderr, "BUS ERR\n");
876
                                        dump();
877
                                        exit(EXIT_FAILURE);
878
                                }
879
                        } else if ((div)&&(diverr)) {
880
                                if (gie()) {
881
                                        m_r[16+14] |= CC_DIVERR;
882
                                        gie(false);
883
                                        m_jumped = true;
884
                                        m_advance_pc = false;
885
                                } else {
886
                                        m_r[14] |= CC_DIVERR;
887
                                        fprintf(stderr, "DIV ERR: division by zero\n");
888
                                        dump();
889
                                        exit(EXIT_FAILURE);
890
                                }
891
                        } if (wf)
892
                                ccodes(f);
893
                        if (wb) {
894
                                if (arg == (uint32_t)(15+rbase()))
895
                                        m_jumped = true;
896
                                else if (arg == (uint32_t)(14+rbase())) {
897
                                        if (gie()) {
898
                                                if ((result & CC_GIE)==0) {
899
                                                        result |= CC_TRAP;
900
                                                        result &= (~(CC_SLEEP
901
                                                        |CC_ILL
902
                                                        |CC_BREAK
903
                                                        |CC_BUSERR
904
                                                        |CC_DIVERR
905
                                                        |CC_FPUERR
906
                                                        |CC_STEP
907
                                                        |CC_SLEEP));
908
                                                }
909
                                        } else if (result & CC_GIE) {
910
                                                // Returning to userspace
911
                                                m_r[16+14] &= (~(CC_ILL
912
                                                        |CC_BREAK
913
                                                        |CC_BUSERR
914
                                                        |CC_DIVERR
915
                                                        |CC_FPUERR));
916
                                        }
917
                                }
918
                                if (dbg) fprintf(stderr,
919
                                        "\tREG[%02x] = %08x\n", arg, result);
920
                                m_r[arg] = result;
921
                                if ((int)arg == 15+rbase())
922
                                        m_advance_pc = false;
923
                                if (((int)arg==14+rbase())&&(((m_gie)?1:0)^((result&CC_GIE)?1:0))) {
924
                                        gie((result&CC_GIE)?true:false);
925
                                        // Prevent us from advancing the PC
926
                                        m_jumped = true;
927
                                        // m_advance_pc = true;
928
                                }
929
                                // Some CC bits are constant.  Keep them that
930
                                // way.
931
                                m_r[14   ] &= (~CC_GIE);
932
                                m_r[14+16] |= ( CC_GIE);
933
                                m_r[15   ] &= -4;
934
                                m_r[15+16] &= -4;
935
                        }
936
                }
937
        }
938
 
939
        void    cisinsn(uint16_t insn) {
940
                uint32_t        imm;
941
                int             dr, br, cisop, fullop;
942
 
943
                cisop = (insn >> 8) & 0x07;
944
                switch(cisop) {
945
                case 0: fullop =  0; break; // SUB
946
                case 1: fullop =  1; break; // AND
947
                case 2: fullop =  2; break; // ADD
948
                case 3: fullop = 16; break; // CMP
949
                case 4: fullop = 18; break; // LW
950
                case 5: fullop = 19; break; // SW
951
                case 6: fullop = 24; break; // LDI
952
                case 7: fullop = 13; break; // MOV
953
                }
954
 
955
                dr = (insn>>11) & 0x0f;
956
 
957
                if (fullop == 24) {
958
                        // LDI
959
                        imm = sbits(insn, 8) & 0x07fffff;
960
                        fullinsn(0x80000000 | (dr<<27) | (fullop<<22) | imm);
961
                } else if (fullop == 13) {
962
                        // MOV
963
                        br = (insn >> 3) & 0x0f;
964
                        imm = sbits(insn, 3) & 0x01fff;
965
                        fullinsn(0x80000000 | (dr << 27) | (fullop<<22) | (br<<14) | imm);
966
                } else if (insn & 0x80) {
967
                        // Uses a breg
968
                        br = (insn >> 3) & 0x0f;
969
                        imm = sbits(insn, 3) & 0x3fff;
970
                        fullinsn(0x80040000 | (dr << 27) | (fullop<<22) | (br<<14) | imm);
971
                } else if ((fullop == 18)||(fullop == 19)) {
972
                        // Load or store, breg is assumed to be SP
973
// 0x04844000
974
                        br = 13;
975
                        imm = sbits(insn, 7) & 0x3fff;
976
                        fullinsn(0x80040000 | (dr << 27) | (fullop<<22) | (br<<14) | imm);
977
                } else {
978
                        imm = sbits(insn, 7) & 0x03ffff;
979
                        fullinsn(0x80000000 | (dr << 27) | (fullop<<22) | imm);
980
                }
981
        }
982
 
983
        void    execute(uint32_t insn) {
984
                /// fprintf(stderr, "EXEC-INSN(@0x%08x - %08x)\n", pc(), insn);
985
                bool    igie = gie();
986
                if (insn & 0x80000000) {
987
                        int             ibase = rbase();
988
                        cisinsn((insn>>16) & 0x0ffff);
989
                        if (m_advance_pc)
990
                                m_r[14+ibase] |= (CC_PHASE);
991
                        if ((!m_jumped)&&(igie == gie())) {
992
                                cisinsn(insn & 0x0ffff);
993
                                m_r[14+ibase] &= ~(CC_PHASE);
994
                        } if (m_advance_pc)
995
                                pc_advance(igie);
996
                        m_jumped = false;
997
                } else {
998
                        m_r[14+rbase()] &= ~(CC_PHASE);
999
                        fullinsn(insn);
1000
 
1001
                        if (m_advance_pc)
1002
                                pc_advance(igie);
1003
 
1004
                        if ((gie())&&(cc() & CC_STEP))
1005
                                gie(false);
1006
                }
1007
        }
1008
};
1009
 
1010
int main(int argc, char **argv) {
1011
        const char *executable = "a.out";
1012
        SIMBUS *bus;
1013
        bool    done;
1014
        ZIPMACHINE      *zipm;
1015
        ELFSECTION      **secpp, *secp;
1016
        uint32_t        entry;
1017
 
1018
        if (argc > 1)
1019
                executable = argv[1];
1020
        if (access(executable, R_OK)!=0) {
1021
                fprintf(stderr, "Cannot read %s\n", executable);
1022
                exit(EXIT_FAILURE);
1023
        } elfread(executable, entry, secpp);
1024
        if (0 == secpp[0]->m_len) {
1025
                fprintf(stderr, "Executable file has no contents!\n");
1026
                exit(EXIT_FAILURE);
1027
        }
1028
 
1029
        // Timer  at 0x0100?
1030
        // Buserr at 0x0101?
1031
        // Addresses are given in 32-bit glory, so they reference 8-bit bytes
1032
        bus = new SIMBUS();
1033
        // BUSITEM net = new NETDEV();
1034
 
1035
        bus->add(new UARTDEV(),  0x00000150, 0xfffffff0, "RW", "UART");// 4 words
1036
        // bus->add(new SDCDEV(12), 0x00000420, 0xfffffff0, "RW");// 4 words
1037
        // bus->add(net->ctrl,   0x00000440, 0xffffffe0, "RW");// 8 words
1038
        // bus->add(net->data,   0x00002000, 0xffffe000, "R"); // 8 words
1039
        // bus->add(net->data,   0x00003000, 0xffffe000, "R"); // 8 words
1040
        bus->add(new MEMDEV(17), 0x0020000, 0x7fe0000, "RWX", "BlockRAM");// Block RAM
1041
        bus->add(new ROMDEV(24),0x01000000,0xff000000, "RXL", "Flash"); // Flash
1042
        bus->add(new MEMDEV(28),0x10000000,0xf0000000, "RWX", "SDRAM");// SDRAM
1043
 
1044
        for(int s=0; secpp[s]->m_len; s++) {
1045
                secp = secpp[s];
1046
                if (false) fprintf(stderr,
1047
                        "Attempting to LOAD->(%08x, ..., %d)\n",
1048
                        secp->m_start, secp->m_len);
1049
                bus->load(secp->m_start, (const char *)&secp->m_data[0], secp->m_len);
1050
                if (bus->error()) {
1051
                        fprintf(stderr, "LOAD: Error writing to mem @ 0x%08x\n", secp->m_start);
1052
                        // exit(EXIT_FAILURE);
1053
                }
1054
        }
1055
 
1056
        if(bus->error()) {
1057
                fprintf(stderr, "ERR: Executable file doesn\'t fit in simulator\n");
1058
                exit(EXIT_FAILURE);
1059
        }
1060
 
1061
        done = false;
1062
        zipm = new ZIPMACHINE;
1063
        if (access("map.txt", R_OK)==0)
1064
                zipm->m_mapf = fopen("map.txt","r");
1065
        zipm->init(bus);
1066
        zipm->m_r[15] = entry;
1067
        while(!done) {
1068
                uint32_t        insn;
1069
                insn = bus->lx(zipm->pc());
1070
 
1071
                if (bus->error()) {
1072
                        if (zipm->gie()) {
1073
                                zipm->m_r[14+16] |= CC_BUSERR;
1074
                                zipm->gie(false);
1075
                                continue;
1076
                        } else {
1077
                                zipm->m_r[14] |= CC_BUSERR;
1078
                                fprintf(stderr, "IFetch BUSERR, %08x\n", zipm->pc());
1079
                                zipm->dump();
1080
                                exit(EXIT_FAILURE);
1081
                        }
1082
                } else {
1083
                        if (!zipm->sleeping())
1084
                                zipm->execute(insn);
1085
                }
1086
 
1087
                if (zipm->halted()) {
1088
                        fflush(stderr);
1089
                        fflush(stdout);
1090
                        printf("CPU HALT\n");
1091
                        done = true;
1092
                        break;
1093
                }
1094
 
1095
                bus->tick();
1096
                if ((bus->interrupt())&&(zipm->gie())&&(!zipm->locked())) {
1097
                        zipm->gie(false);
1098
                        zipm->sleep(false);
1099
                }
1100
        }
1101
}
1102
 

powered by: WebSVN 2.1.0

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