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

Subversion Repositories zipcpu

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

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

powered by: WebSVN 2.1.0

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