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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [cpu_fnc_plugin/] [riscv-rv64i-user.cpp] - Blame information for rev 3

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

Line No. Rev Author Line
1 3 sergeykhbr
/**
2
 * @file
3
 * @copyright  Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
5
 * @brief      Base ISA implementation (extension I, user level).
6
 */
7
 
8
#include "api_utils.h"
9
#include "riscv-isa.h"
10
#include "instructions.h"
11
 
12
namespace debugger {
13
 
14
void generateException(uint64_t code, CpuContextType *data);
15
 
16
/**
17
 * @brief Addition. Overflows are ignored
18
 */
19
class ADD : public IsaProcessor {
20
public:
21
    ADD() : IsaProcessor("ADD", "0000000??????????000?????0110011") {}
22
 
23
    virtual void exec(uint32_t *payload, CpuContextType *data) {
24
        ISA_R_type u;
25
        u.value = payload[0];
26
        data->regs[u.bits.rd] =
27
                data->regs[u.bits.rs1] + data->regs[u.bits.rs2];
28
        data->npc = data->pc + 4;
29
    }
30
};
31
 
32
/**
33
 * @brief Add immediate
34
 *
35
 * ADDI adds the sign-extended 12-bit immediate to register rs1.
36
 * Arithmetic overflow is ignored and the result is simply the low 32-bits of
37
 * the result. ADDI rd, rs1, 0 is used to implement the MV rd, rs1 assembler
38
 * pseudo-instruction.
39
 */
40
class ADDI : public IsaProcessor {
41
public:
42
    ADDI() : IsaProcessor("ADDI", "?????????????????000?????0010011") {}
43
 
44
    virtual void exec(uint32_t *payload, CpuContextType *data) {
45
        ISA_I_type u;
46
        u.value = payload[0];
47
 
48
        uint64_t imm = u.bits.imm;
49
        if (imm & 0x800) {
50
            imm |= EXT_SIGN_12;
51
        }
52
        data->regs[u.bits.rd] = data->regs[u.bits.rs1] + imm;
53
        data->npc = data->pc + 4;
54
 
55
        if (u.bits.rs1 == 0) {
56
            RISCV_sprintf(data->disasm, sizeof(data->disasm),
57
                "li %s,%d", IREGS_NAMES[u.bits.rd], static_cast<uint32_t>(imm));
58
        } else {
59
            RISCV_sprintf(data->disasm, sizeof(data->disasm),
60
                "addi %s,%s,%d", IREGS_NAMES[u.bits.rd],
61
                                 IREGS_NAMES[u.bits.rs1],
62
                                 static_cast<uint32_t>(imm));
63
        }
64
    }
65
};
66
 
67
/**
68
 * @brief Add immediate with sign extending (RV64I)
69
 *
70
 * ADDIW is an RV64I-only instruction that adds the sign-extended 12-bit
71
 * immediate to register rs1 and produces the proper sign-extension of
72
 * a 32-bit result in rd. Overflows are ignored and the result is the low
73
 * 32 bits of the result sign-extended to 64 bits. Note, ADDIW rd, rs1, 0
74
 * writes the sign-extension of the lower 32 bits of register rs1 into
75
 * register rd (assembler pseudo-op SEXT.W).
76
 */
77
class ADDIW : public IsaProcessor {
78
public:
79
    ADDIW() : IsaProcessor("ADDIW", "?????????????????000?????0011011") {}
80
 
81
    virtual void exec(uint32_t *payload, CpuContextType *data) {
82
        ISA_I_type u;
83
        u.value = payload[0];
84
 
85
        uint64_t imm = u.bits.imm;
86
        if (imm & 0x800) {
87
            imm |= EXT_SIGN_12;
88
        }
89
        data->regs[u.bits.rd] = (data->regs[u.bits.rs1] + imm) & 0xFFFFFFFFLL;
90
        if (data->regs[u.bits.rd] & (1LL << 31)) {
91
            data->regs[u.bits.rd] |= EXT_SIGN_32;
92
        }
93
        data->npc = data->pc + 4;
94
 
95
        if (u.bits.imm == 0) {
96
            //RISCV_sprintf(data->disasm, sizeof(data->disasm), "sext.w %s,%d",);
97
        } else {
98
            //RISCV_sprintf(data->disasm, sizeof(data->disasm), "addiw %s,%s,%d",);
99
        }
100
    }
101
};
102
 
103
/**
104
 * @brief Add registers with sign extending (RV64I)
105
 *
106
 * ADDW is RV64I-only instructions that are defined analogously to
107
 * ADD but operate on 32-bit values and produce signed 32-bit results.
108
 * Overflows are ignored, and the low 32-bits of the result is sign-extended
109
 * to 64-bits and written to the destination register.
110
 */
111
class ADDW : public IsaProcessor {
112
public:
113
    ADDW() : IsaProcessor("ADDW", "0000000??????????000?????0111011") {}
114
 
115
    virtual void exec(uint32_t *payload, CpuContextType *data) {
116
        ISA_R_type u;
117
        u.value = payload[0];
118
 
119
        data->regs[u.bits.rd] =
120
            (data->regs[u.bits.rs1] + data->regs[u.bits.rs2]) & 0xFFFFFFFFLL;
121
        if (data->regs[u.bits.rd] & (1LL << 31)) {
122
            data->regs[u.bits.rd] |= EXT_SIGN_32;
123
        }
124
        data->npc = data->pc + 4;
125
    }
126
};
127
 
128
/**
129
 * @brief AND bitwise logical operation.
130
 */
131
class AND : public IsaProcessor {
132
public:
133
    AND() : IsaProcessor("AND", "0000000??????????111?????0110011") {}
134
 
135
    virtual void exec(uint32_t *payload, CpuContextType *data) {
136
        ISA_R_type u;
137
        u.value = payload[0];
138
        data->regs[u.bits.rd] =
139
                data->regs[u.bits.rs1] & data->regs[u.bits.rs2];
140
        data->npc = data->pc + 4;
141
    }
142
};
143
 
144
/**
145
 * @brief ANDI logical operation with immediate.
146
 *
147
 * ANDI, ORI, XORI are logical operations that perform bitwise AND, OR,
148
 * and XOR on register rs1 and the sign-extended 12-bit immediate and place
149
 * the result in rd.
150
 */
151
class ANDI : public IsaProcessor {
152
public:
153
    ANDI() : IsaProcessor("ANDI", "?????????????????111?????0010011") {}
154
 
155
    virtual void exec(uint32_t *payload, CpuContextType *data) {
156
        ISA_I_type u;
157
        u.value = payload[0];
158
        uint64_t imm = u.bits.imm;
159
        if (imm & 0x800) {
160
            imm |= EXT_SIGN_12;
161
        }
162
 
163
        data->regs[u.bits.rd] = data->regs[u.bits.rs1] & imm;
164
        data->npc = data->pc + 4;
165
    }
166
};
167
 
168
/**
169
 * @brief AUIPC (add upper immediate to pc)
170
 *
171
 * AUIPC is used to build pc-relative addresses and uses the U-type
172
 * format. AUIPC forms a 32-bit offset from the 20-bit U-immediate,
173
 * filling in the lowest 12 bits with zeros, adds this offset to the pc,
174
 * then places the result in register rd.
175
 */
176
class AUIPC : public IsaProcessor {
177
public:
178
    AUIPC() : IsaProcessor("AUIPC", "?????????????????????????0010111") {}
179
 
180
    virtual void exec(uint32_t *payload, CpuContextType *data) {
181
        ISA_U_type u;
182
        u.value = payload[0];
183
 
184
        uint64_t off = u.bits.imm31_12 << 12;
185
        if (off & (1LL << 31)) {
186
            off |= EXT_SIGN_32;
187
        }
188
        data->regs[u.bits.rd] = data->pc + off;
189
        data->npc = data->pc + 4;
190
    }
191
};
192
 
193
/**
194
 * @brief The BEQ (Branch if registers are equal)
195
 */
196
class BEQ : public IsaProcessor {
197
public:
198
    BEQ() : IsaProcessor("BEQ", "?????????????????000?????1100011") {}
199
 
200
    virtual void exec(uint32_t *payload, CpuContextType *data) {
201
        ISA_SB_type u;
202
        u.value = payload[0];
203
 
204
        if (data->regs[u.bits.rs1] == data->regs[u.bits.rs2]) {
205
            uint64_t imm = (u.bits.imm12 << 12) | (u.bits.imm11 << 11)
206
                    | (u.bits.imm10_5 << 5) | (u.bits.imm4_1 << 1);
207
            if (u.bits.imm12) {
208
                imm |= EXT_SIGN_12;
209
            }
210
            data->npc = data->pc + imm;
211
        } else {
212
            data->npc = data->pc + 4;
213
        }
214
    }
215
};
216
 
217
/**
218
 * @brief The BGE (Branch if greater than or equal using signed comparision)
219
 *
220
 * All branch instructions use the SB-type instruction format. The 12-bit
221
 * B-immediate encodes signed offsets in multiples of 2, and is added to the
222
 * current pc to give the target address. The conditional branch range
223
 * is ±4 KiB.
224
 */
225
class BGE : public IsaProcessor {
226
public:
227
    BGE() : IsaProcessor("BGE", "?????????????????101?????1100011") {}
228
 
229
    virtual void exec(uint32_t *payload, CpuContextType *data) {
230
        ISA_SB_type u;
231
        u.value = payload[0];
232
 
233
        if (static_cast<int64_t>(data->regs[u.bits.rs1]) >=
234
            static_cast<int64_t>(data->regs[u.bits.rs2])) {
235
            uint64_t imm = (u.bits.imm12 << 12) | (u.bits.imm11 << 11)
236
                    | (u.bits.imm10_5 << 5) | (u.bits.imm4_1 << 1);
237
            if (u.bits.imm12) {
238
                imm |= EXT_SIGN_12;
239
            }
240
            data->npc = data->pc + imm;
241
        } else {
242
            data->npc = data->pc + 4;
243
        }
244
    }
245
};
246
 
247
 
248
/**
249
 * @brief The BGEU (Branch if greater than or equal using unsigned comparision)
250
 */
251
class BGEU : public IsaProcessor {
252
public:
253
    BGEU() : IsaProcessor("BGEU", "?????????????????111?????1100011") {}
254
 
255
    virtual void exec(uint32_t *payload, CpuContextType *data) {
256
        ISA_SB_type u;
257
        u.value = payload[0];
258
 
259
        if (data->regs[u.bits.rs1] >= data->regs[u.bits.rs2]) {
260
            uint64_t imm = (u.bits.imm12 << 12) | (u.bits.imm11 << 11)
261
                    | (u.bits.imm10_5 << 5) | (u.bits.imm4_1 << 1);
262
            if (u.bits.imm12) {
263
                imm |= EXT_SIGN_12;
264
            }
265
            data->npc = data->pc + imm;
266
        } else {
267
            data->npc = data->pc + 4;
268
        }
269
    }
270
};
271
 
272
/**
273
 * @brief The BLT (Branch if less than using signed comparision)
274
 */
275
class BLT : public IsaProcessor {
276
public:
277
    BLT() : IsaProcessor("BLT", "?????????????????100?????1100011") {}
278
 
279
    virtual void exec(uint32_t *payload, CpuContextType *data) {
280
        ISA_SB_type u;
281
        u.value = payload[0];
282
 
283
        if (static_cast<int64_t>(data->regs[u.bits.rs1]) <
284
            static_cast<int64_t>(data->regs[u.bits.rs2])) {
285
            uint64_t imm = (u.bits.imm12 << 12) | (u.bits.imm11 << 11)
286
                    | (u.bits.imm10_5 << 5) | (u.bits.imm4_1 << 1);
287
            if (u.bits.imm12) {
288
                imm |= EXT_SIGN_12;
289
            }
290
            data->npc = data->pc + imm;
291
        } else {
292
            data->npc = data->pc + 4;
293
        }
294
    }
295
};
296
 
297
/**
298
 * @brief The BLTU (Branch if less than using unsigned comparision)
299
 */
300
class BLTU : public IsaProcessor {
301
public:
302
    BLTU() : IsaProcessor("BLTU", "?????????????????110?????1100011") {}
303
 
304
    virtual void exec(uint32_t *payload, CpuContextType *data) {
305
        ISA_SB_type u;
306
        u.value = payload[0];
307
 
308
        if (data->regs[u.bits.rs1] < data->regs[u.bits.rs2]) {
309
            uint64_t imm = (u.bits.imm12 << 12) | (u.bits.imm11 << 11)
310
                    | (u.bits.imm10_5 << 5) | (u.bits.imm4_1 << 1);
311
            if (u.bits.imm12) {
312
                imm |= EXT_SIGN_12;
313
            }
314
            data->npc = data->pc + imm;
315
        } else {
316
            data->npc = data->pc + 4;
317
        }
318
    }
319
};
320
 
321
/**
322
 * @brief The BNE (Branch if registers are unequal)
323
 */
324
class BNE : public IsaProcessor {
325
public:
326
    BNE() : IsaProcessor("BNE", "?????????????????001?????1100011") {}
327
 
328
    virtual void exec(uint32_t *payload, CpuContextType *data) {
329
        ISA_SB_type u;
330
        u.value = payload[0];
331
 
332
        if (data->regs[u.bits.rs1] != data->regs[u.bits.rs2]) {
333
            uint64_t imm = (u.bits.imm12 << 12) | (u.bits.imm11 << 11)
334
                    | (u.bits.imm10_5 << 5) | (u.bits.imm4_1 << 1);
335
            if (u.bits.imm12) {
336
                imm |= EXT_SIGN_12;
337
            }
338
            data->npc = data->pc + imm;
339
        } else {
340
            data->npc = data->pc + 4;
341
        }
342
    }
343
};
344
 
345
/**
346
 * @brief JAL (Jump and link).
347
 *
348
 * Unconditional jump. The offset is sign-extended and added to the pc to form
349
 * the jump target address. Jumps can therefore target a ±1 MiB range. JAL
350
 * stores the address of the instruction following the jump (pc+4) into
351
 * register rd. The standard software calling convention uses x1 as the return
352
 * address register.
353
 *
354
 * J (pseudo-op) 0 Plain unconditional jumps are encoded as a JAL with rd=x0.
355
 */
356
class JAL : public IsaProcessor {
357
public:
358
    JAL() : IsaProcessor("JAL", "?????????????????????????1101111") {}
359
 
360
    virtual void exec(uint32_t *payload, CpuContextType *data) {
361
        ISA_UJ_type u;
362
        u.value = payload[0];
363
        uint64_t off = 0;
364
        if (u.bits.imm20) {
365
            off = 0xfffffffffff00000LL;
366
        }
367
        off |= (u.bits.imm19_12 << 12);
368
        off |= (u.bits.imm11 << 11);
369
        off |= (u.bits.imm10_1 << 1);
370
        if (u.bits.rd != 0) {
371
            data->regs[u.bits.rd] = data->pc + 4;
372
        }
373
        data->npc = data->pc + off;
374
        if (u.bits.rd == Reg_ra) {
375
            if (data->stack_trace_cnt < STACK_TRACE_BUF_SIZE/2) {
376
                data->stack_trace_buf[2*data->stack_trace_cnt] = data->pc;
377
                data->stack_trace_buf[2*data->stack_trace_cnt] &= ~0x1;
378
                data->stack_trace_buf[2*data->stack_trace_cnt+1] = data->npc;
379
            }
380
            data->stack_trace_cnt++;
381
        }
382
    }
383
};
384
 
385
/**
386
 * @brief JALR (Jump and link register).
387
 *
388
 * The target address is obtained by adding the 12-bit signed I-immediate to
389
 * the register rs1, then setting the least-significant bit of the result to
390
 * zero. The address of the instruction following the jump (pc+4) is written
391
 * to register rd. Register x0 can be used as the destination if the result
392
 * is not required.
393
 */
394
class JALR : public IsaProcessor {
395
public:
396
    JALR() : IsaProcessor("JALR", "?????????????????000?????1100111") {}
397
 
398
    virtual void exec(uint32_t *payload, CpuContextType *data) {
399
        ISA_I_type u;
400
        u.value = payload[0];
401
        uint64_t off = u.bits.imm;
402
        if (u.bits.imm & 0x800) {
403
            off |= 0xfffffffffffff000LL;
404
        }
405
        off += data->regs[u.bits.rs1];
406
        off &= ~0x1LL;
407
        if (u.bits.rd != 0) {
408
            data->regs[u.bits.rd] = data->pc + 4;
409
        }
410
        data->npc = off;
411
 
412
        // Stack trace buffer:
413
        if (u.bits.rd == Reg_ra) {
414
            if (data->stack_trace_cnt < STACK_TRACE_BUF_SIZE/2) {
415
                data->stack_trace_buf[2*data->stack_trace_cnt] = data->pc;
416
                data->stack_trace_buf[2*data->stack_trace_cnt] &= ~0x1;
417
                data->stack_trace_buf[2*data->stack_trace_cnt+1] = data->npc;
418
            }
419
            data->stack_trace_cnt++;
420
        } else if (u.bits.imm == 0 && u.bits.rs1 == Reg_ra
421
            && data->stack_trace_cnt) {
422
            data->stack_trace_cnt--;
423
        }
424
    }
425
};
426
 
427
/**
428
 * @brief LOAD instructions (LD, LW, LH, LB) with sign extending.
429
 *
430
 * Loads copy a value from memory to register rd.
431
 * The effective byte address is obtained by adding register rs1 to the
432
 * sign-extended 12-bit offset.
433
 *   The LW instruction loads a 32-bit value from memory into rd. LH loads
434
 * a 16-bit value from memory, then sign-extends to 32-bits before storing
435
 * in rd.
436
 */
437
class LD : public IsaProcessor {
438
public:
439
    LD() : IsaProcessor("LD", "?????????????????011?????0000011") {}
440
 
441
    virtual void exec(uint32_t *payload, CpuContextType *data) {
442
        Axi4TransactionType trans;
443
        ISA_I_type u;
444
        u.value = payload[0];
445
        uint64_t off = u.bits.imm;
446
        if (off & 0x800) {
447
            off |= EXT_SIGN_12;
448
        }
449
        trans.source_idx = CFG_NASTI_MASTER_CACHED;
450
        trans.action = MemAction_Read;
451
        trans.addr = data->regs[u.bits.rs1] + off;
452
        trans.xsize = 8;
453
        if (trans.addr & 0x7) {
454
            trans.rpayload.b64[0] = 0;
455
            generateException(EXCEPTION_LoadMisalign, data);
456
        } else {
457
            data->ibus->b_transport(&trans);
458
            data->npc = data->pc + 4;
459
        }
460
        data->regs[u.bits.rd] = trans.rpayload.b64[0];
461
        if (data->mem_trace_file) {
462
            char tstr[512];
463
            RISCV_sprintf(tstr, sizeof(tstr),
464
                        "%08x: [%08x] => %016" RV_PRI64 "x\n",
465
                        static_cast<int>(data->pc),
466
                        static_cast<int>(trans.addr), trans.rpayload.b64[0]);
467
            (*data->mem_trace_file) << tstr;
468
            data->mem_trace_file->flush();
469
        }
470
    }
471
};
472
 
473
/**
474
 * Load 32-bits with sign extending.
475
 */
476
class LW : public IsaProcessor {
477
public:
478
    LW() : IsaProcessor("LW", "?????????????????010?????0000011") {}
479
 
480
    virtual void exec(uint32_t *payload, CpuContextType *data) {
481
        Axi4TransactionType trans;
482
        trans.source_idx = CFG_NASTI_MASTER_CACHED;
483
        trans.rpayload.b64[0] = 0;
484
        ISA_I_type u;
485
        u.value = payload[0];
486
        uint64_t off = u.bits.imm;
487
        if (off & 0x800) {
488
            off |= EXT_SIGN_12;
489
        }
490
        trans.action = MemAction_Read;
491
        trans.addr = data->regs[u.bits.rs1] + off;
492
        trans.xsize = 4;
493
        if (trans.addr & 0x3) {
494
            trans.rpayload.b64[0] = 0;
495
            generateException(EXCEPTION_LoadMisalign, data);
496
        } else {
497
            data->ibus->b_transport(&trans);
498
            data->npc = data->pc + 4;
499
        }
500
        data->regs[u.bits.rd] = trans.rpayload.b64[0];
501
        if (data->regs[u.bits.rd] & (1LL << 31)) {
502
            data->regs[u.bits.rd] |= EXT_SIGN_32;
503
        }
504
        if (data->mem_trace_file) {
505
            char tstr[512];
506
            RISCV_sprintf(tstr, sizeof(tstr),
507
                    "%08x: [%08x] => %016" RV_PRI64 "x\n",
508
                    static_cast<int>(data->pc),
509
                    static_cast<int>(trans.addr), trans.rpayload.b64[0]);
510
            (*data->mem_trace_file) << tstr;
511
            data->mem_trace_file->flush();
512
        }
513
    }
514
};
515
 
516
/**
517
 * Load 32-bits with zero extending.
518
 */
519
class LWU : public IsaProcessor {
520
public:
521
    LWU() : IsaProcessor("LWU", "?????????????????110?????0000011") {}
522
 
523
    virtual void exec(uint32_t *payload, CpuContextType *data) {
524
        Axi4TransactionType trans;
525
        trans.source_idx = CFG_NASTI_MASTER_CACHED;
526
        trans.rpayload.b64[0] = 0;
527
        ISA_I_type u;
528
        u.value = payload[0];
529
        uint64_t off = u.bits.imm;
530
        if (off & 0x800) {
531
            off |= EXT_SIGN_12;
532
        }
533
        trans.action = MemAction_Read;
534
        trans.addr = data->regs[u.bits.rs1] + off;
535
        trans.xsize = 4;
536
        if (trans.addr & 0x3) {
537
            trans.rpayload.b64[0] = 0;
538
            generateException(EXCEPTION_LoadMisalign, data);
539
        } else {
540
            data->ibus->b_transport(&trans);
541
            data->npc = data->pc + 4;
542
        }
543
        data->regs[u.bits.rd] = trans.rpayload.b64[0];
544
        if (data->mem_trace_file) {
545
            char tstr[512];
546
            RISCV_sprintf(tstr, sizeof(tstr),
547
                    "%08x: [%08x] => %016" RV_PRI64 "x\n",
548
                    static_cast<int>(data->pc),
549
                    static_cast<int>(trans.addr), trans.rpayload.b64[0]);
550
            (*data->mem_trace_file) << tstr;
551
            data->mem_trace_file->flush();
552
        }
553
    }
554
};
555
 
556
/**
557
 * Load 16-bits with sign extending.
558
 */
559
class LH : public IsaProcessor {
560
public:
561
    LH() : IsaProcessor("LH", "?????????????????001?????0000011") {}
562
 
563
    virtual void exec(uint32_t *payload, CpuContextType *data) {
564
        Axi4TransactionType trans;
565
        trans.source_idx = CFG_NASTI_MASTER_CACHED;
566
        trans.rpayload.b64[0] = 0;
567
        ISA_I_type u;
568
        u.value = payload[0];
569
        uint64_t off = u.bits.imm;
570
        if (off & 0x800) {
571
            off |= EXT_SIGN_12;
572
        }
573
        trans.action = MemAction_Read;
574
        trans.addr = data->regs[u.bits.rs1] + off;
575
        trans.xsize = 2;
576
        if (trans.addr & 0x1) {
577
            trans.rpayload.b64[0] = 0;
578
            generateException(EXCEPTION_LoadMisalign, data);
579
        } else {
580
            data->ibus->b_transport(&trans);
581
            data->npc = data->pc + 4;
582
        }
583
        data->regs[u.bits.rd] = trans.rpayload.b16[0];
584
        if (data->regs[u.bits.rd] & (1LL << 15)) {
585
            data->regs[u.bits.rd] |= EXT_SIGN_16;
586
        }
587
        if (data->mem_trace_file) {
588
            char tstr[512];
589
            RISCV_sprintf(tstr, sizeof(tstr),
590
                        "%08x: [%08x] => %016" RV_PRI64 "x\n",
591
                        static_cast<int>(data->pc),
592
                        static_cast<int>(trans.addr), trans.rpayload.b64[0]);
593
            (*data->mem_trace_file) << tstr;
594
            data->mem_trace_file->flush();
595
        }
596
    }
597
};
598
 
599
/**
600
 * Load 16-bits with zero extending.
601
 */
602
class LHU : public IsaProcessor {
603
public:
604
    LHU() : IsaProcessor("LHU", "?????????????????101?????0000011") {}
605
 
606
    virtual void exec(uint32_t *payload, CpuContextType *data) {
607
        Axi4TransactionType trans;
608
        trans.source_idx = CFG_NASTI_MASTER_CACHED;
609
        trans.rpayload.b64[0] = 0;
610
        ISA_I_type u;
611
        u.value = payload[0];
612
        uint64_t off = u.bits.imm;
613
        if (off & 0x800) {
614
            off |= EXT_SIGN_12;
615
        }
616
        trans.action = MemAction_Read;
617
        trans.addr = data->regs[u.bits.rs1] + off;
618
        trans.xsize = 2;
619
        if (trans.addr & 0x1) {
620
            trans.rpayload.b64[0] = 0;
621
            generateException(EXCEPTION_LoadMisalign, data);
622
        } else {
623
            data->ibus->b_transport(&trans);
624
            data->npc = data->pc + 4;
625
        }
626
        data->regs[u.bits.rd] = trans.rpayload.b16[0];
627
        if (data->mem_trace_file) {
628
            char tstr[512];
629
            RISCV_sprintf(tstr, sizeof(tstr),
630
                        "%08x: [%08x] => %016" RV_PRI64 "x\n",
631
                        static_cast<int>(data->pc),
632
                        static_cast<int>(trans.addr), trans.rpayload.b64[0]);
633
            (*data->mem_trace_file) << tstr;
634
            data->mem_trace_file->flush();
635
        }
636
    }
637
};
638
 
639
/**
640
 * Load 8-bits with sign extending.
641
 */
642
class LB : public IsaProcessor {
643
public:
644
    LB() : IsaProcessor("LB", "?????????????????000?????0000011") {}
645
 
646
    virtual void exec(uint32_t *payload, CpuContextType *data) {
647
        Axi4TransactionType trans;
648
        trans.source_idx = CFG_NASTI_MASTER_CACHED;
649
        trans.rpayload.b64[0] = 0;
650
        ISA_I_type u;
651
        u.value = payload[0];
652
        uint64_t off = u.bits.imm;
653
        if (off & 0x800) {
654
            off |= EXT_SIGN_12;
655
        }
656
        trans.action = MemAction_Read;
657
        trans.addr = data->regs[u.bits.rs1] + off;
658
        trans.xsize = 1;
659
        data->ibus->b_transport(&trans);
660
        data->regs[u.bits.rd] = trans.rpayload.b8[0];
661
        if (data->regs[u.bits.rd] & (1LL << 7)) {
662
            data->regs[u.bits.rd] |= EXT_SIGN_8;
663
        }
664
        data->npc = data->pc + 4;
665
        if (data->mem_trace_file) {
666
            char tstr[512];
667
            RISCV_sprintf(tstr, sizeof(tstr),
668
                        "%08x: [%08x] => %016" RV_PRI64 "x\n",
669
                        static_cast<int>(data->pc),
670
                        static_cast<int>(trans.addr), trans.rpayload.b64[0]);
671
            (*data->mem_trace_file) << tstr;
672
            data->mem_trace_file->flush();
673
        }
674
    }
675
};
676
 
677
/**
678
 * Load 8-bits with zero extending.
679
 */
680
class LBU : public IsaProcessor {
681
public:
682
    LBU() : IsaProcessor("LBU", "?????????????????100?????0000011") {}
683
 
684
    virtual void exec(uint32_t *payload, CpuContextType *data) {
685
        Axi4TransactionType trans;
686
        trans.source_idx = CFG_NASTI_MASTER_CACHED;
687
        trans.rpayload.b64[0] = 0;
688
        ISA_I_type u;
689
        u.value = payload[0];
690
        uint64_t off = u.bits.imm;
691
        if (off & 0x800) {
692
            off |= EXT_SIGN_12;
693
        }
694
        trans.action = MemAction_Read;
695
        trans.addr = data->regs[u.bits.rs1] + off;
696
        trans.xsize = 1;
697
        data->ibus->b_transport(&trans);
698
        data->regs[u.bits.rd] = trans.rpayload.b8[0];
699
        data->npc = data->pc + 4;
700
        if (data->mem_trace_file) {
701
            char tstr[512];
702
            RISCV_sprintf(tstr, sizeof(tstr),
703
                    "%08x: [%08x] => %016" RV_PRI64 "x\n",
704
                    static_cast<int>(data->pc),
705
                    static_cast<int>(trans.addr), trans.rpayload.b64[0]);
706
            (*data->mem_trace_file) << tstr;
707
            data->mem_trace_file->flush();
708
        }
709
    }
710
};
711
 
712
/**
713
 * @brief LUI (load upper immediate).
714
 *
715
 * It is used to build 32-bit constants and uses the U-type format. LUI places
716
 * the U-immediate value in the top 20 bits of the destination register rd,
717
 * filling in the lowest 12 bits with zeros.
718
 */
719
class LUI : public IsaProcessor {
720
public:
721
    LUI() : IsaProcessor("LUI", "?????????????????????????0110111") {}
722
 
723
    virtual void exec(uint32_t *payload, CpuContextType *data) {
724
        ISA_U_type u;
725
        u.value = payload[0];
726
        uint64_t tmp = u.bits.imm31_12 << 12;
727
        if (tmp & 0x80000000) {
728
            tmp |= EXT_SIGN_32;
729
        }
730
        data->regs[u.bits.rd] = tmp;
731
        data->npc = data->pc + 4;
732
    }
733
};
734
 
735
/**
736
 * @brief OR bitwise operation
737
 */
738
class OR : public IsaProcessor {
739
public:
740
    OR() : IsaProcessor("OR", "0000000??????????110?????0110011") {}
741
 
742
    virtual void exec(uint32_t *payload, CpuContextType *data) {
743
        ISA_R_type u;
744
        u.value = payload[0];
745
        data->regs[u.bits.rd] =
746
                data->regs[u.bits.rs1] | data->regs[u.bits.rs2];
747
        data->npc = data->pc + 4;
748
    }
749
};
750
 
751
/**
752
 * @brief OR on register rs1 and the sign-extended 12-bit immediate.
753
 */
754
class ORI : public IsaProcessor {
755
public:
756
    ORI() : IsaProcessor("ORI", "?????????????????110?????0010011") {}
757
 
758
    virtual void exec(uint32_t *payload, CpuContextType *data) {
759
        ISA_I_type u;
760
        u.value = payload[0];
761
 
762
        uint64_t imm = u.bits.imm;
763
        if (imm & 0x800) {
764
            imm |= EXT_SIGN_12;
765
        }
766
        data->regs[u.bits.rd] = data->regs[u.bits.rs1] | imm;
767
        data->npc = data->pc + 4;
768
    }
769
};
770
 
771
/**
772
 * @brief SLLI is a logical left shift (zeros are shifted into the lower bits)
773
 */
774
class SLLI : public IsaProcessor {
775
public:
776
    SLLI() : IsaProcessor("SLLI", "000000???????????001?????0010011") {}
777
 
778
    virtual void exec(uint32_t *payload, CpuContextType *data) {
779
        ISA_I_type u;
780
        u.value = payload[0];
781
        uint32_t shamt = u.bits.imm & 0x3f;
782
        data->regs[u.bits.rd] = data->regs[u.bits.rs1] << shamt;
783
        data->npc = data->pc + 4;
784
    }
785
};
786
 
787
/**
788
 * @brief The SLT (signed comparision)
789
 *
790
 * It places the value 1 in register rd if rs1 < rs2, 0 otherwise
791
 */
792
class SLT : public IsaProcessor {
793
public:
794
    SLT() : IsaProcessor("SLT", "0000000??????????010?????0110011") {}
795
 
796
    virtual void exec(uint32_t *payload, CpuContextType *data) {
797
        ISA_R_type u;
798
        u.value = payload[0];
799
        if (static_cast<int64_t>(data->regs[u.bits.rs1]) <
800
                static_cast<int64_t>(data->regs[u.bits.rs2])) {
801
            data->regs[u.bits.rd] = 1;
802
        } else {
803
            data->regs[u.bits.rd] = 0;
804
        }
805
        data->npc = data->pc + 4;
806
    }
807
};
808
 
809
/**
810
 * @brief The SLTI (set less than immediate)
811
 *
812
 * It places the value 1 in register rd if register rs1 is less than the
813
 * sign-extended immediate when both are treated as signed numbers, else 0
814
 * is written to rd.
815
 */
816
class SLTI : public IsaProcessor {
817
public:
818
    SLTI() : IsaProcessor("SLTI", "?????????????????010?????0010011") {}
819
 
820
    virtual void exec(uint32_t *payload, CpuContextType *data) {
821
        ISA_I_type u;
822
        u.value = payload[0];
823
 
824
        uint64_t imm = u.bits.imm;
825
        if (imm & 0x800) {
826
            imm |= EXT_SIGN_12;
827
        }
828
        if (static_cast<int64_t>(data->regs[u.bits.rs1]) <
829
                static_cast<int64_t>(imm)) {
830
            data->regs[u.bits.rd] = 1;
831
        } else {
832
            data->regs[u.bits.rd] = 0;
833
        }
834
        data->npc = data->pc + 4;
835
    }
836
};
837
 
838
/**
839
 * @brief The SLTU (unsigned comparision)
840
 *
841
 * SLTU perform unsigned compares, writing 1 to rd if rs1 < rs2, 0 otherwise.
842
 * @note SLTU rd, x0, rs2 sets rd to 1 if rs2 is not equal to zero, otherwise
843
 * sets rd to zero (assembler pseudo-op SNEZ rd, rs).
844
 */
845
class SLTU : public IsaProcessor {
846
public:
847
    SLTU() : IsaProcessor("SLTU", "0000000??????????011?????0110011") {}
848
 
849
    virtual void exec(uint32_t *payload, CpuContextType *data) {
850
        ISA_R_type u;
851
        u.value = payload[0];
852
        if (data->regs[u.bits.rs1] < data->regs[u.bits.rs2]) {
853
            data->regs[u.bits.rd] = 1;
854
        } else {
855
            data->regs[u.bits.rd] = 0;
856
        }
857
        data->npc = data->pc + 4;
858
    }
859
};
860
 
861
/**
862
 * @brief The SLTIU (set less than immediate comparing unsgined values)
863
 *
864
 * SLTIU is similar but compares the values as unsigned numbers (i.e., the
865
 * immediate is first sign-extended to 32-bits then treated as an unsigned
866
 * number). Note, SLTIU rd, rs1, 1 sets rd to 1 if rs1 equals zero, otherwise
867
 * sets rd to 0 (assembler pseudo-op SEQZ rd, rs).
868
 */
869
class SLTIU : public IsaProcessor {
870
public:
871
    SLTIU() : IsaProcessor("SLTIU", "?????????????????011?????0010011") {}
872
 
873
    virtual void exec(uint32_t *payload, CpuContextType *data) {
874
        ISA_I_type u;
875
        u.value = payload[0];
876
 
877
        uint64_t imm = u.bits.imm;
878
        if (imm & 0x800) {
879
            imm |= EXT_SIGN_12;
880
        }
881
        if (data->regs[u.bits.rs1] < imm) {
882
            data->regs[u.bits.rd] = 1;
883
        } else {
884
            data->regs[u.bits.rd] = 0;
885
        }
886
        data->npc = data->pc + 4;
887
    }
888
};
889
 
890
/**
891
 * @brief SLL logical shift left
892
 */
893
class SLL : public IsaProcessor {
894
public:
895
    SLL() : IsaProcessor("SLL", "0000000??????????001?????0110011") {}
896
 
897
    virtual void exec(uint32_t *payload, CpuContextType *data) {
898
        ISA_R_type u;
899
        u.value = payload[0];
900
        data->regs[u.bits.rd] =
901
            data->regs[u.bits.rs1] << (data->regs[u.bits.rs2] & 0x3F);
902
        data->npc = data->pc + 4;
903
    }
904
};
905
 
906
 
907
/**
908
 * @brief SLLW is a left shifts by register defined value (RV64I).
909
 */
910
class SLLW : public IsaProcessor {
911
public:
912
    SLLW() : IsaProcessor("SLLW", "0000000??????????001?????0111011") {}
913
 
914
    virtual void exec(uint32_t *payload, CpuContextType *data) {
915
        ISA_R_type u;
916
        u.value = payload[0];
917
        data->regs[u.bits.rd] = data->regs[u.bits.rs1] << data->regs[u.bits.rs2];
918
        data->regs[u.bits.rd] &= 0xFFFFFFFFLL;
919
        if (data->regs[u.bits.rd] & (1LL << 31)) {
920
            data->regs[u.bits.rd] |= EXT_SIGN_32;
921
        }
922
        data->npc = data->pc + 4;
923
    }
924
};
925
 
926
/**
927
 * @brief SLLIW is a shifts by a constant (RV64I).
928
 *
929
 * SLLIW, SRLIW, and SRAIW are RV64I-only instructions that operate on 32-bit
930
 * values and produce signed 32-bit results.
931
 * @exception Illegal_Instruction if imm[5] not equal to 0.
932
 */
933
class SLLIW : public IsaProcessor {
934
public:
935
    SLLIW() : IsaProcessor("SLLIW", "0000000??????????001?????0011011") {}
936
 
937
    virtual void exec(uint32_t *payload, CpuContextType *data) {
938
        ISA_I_type u;
939
        u.value = payload[0];
940
        uint32_t shamt = u.bits.imm & 0x1f;
941
        data->regs[u.bits.rd] = data->regs[u.bits.rs1] << shamt;
942
        data->regs[u.bits.rd] &= 0xFFFFFFFFLL;
943
        if (data->regs[u.bits.rd] & (1LL << 31)) {
944
            data->regs[u.bits.rd] |= EXT_SIGN_32;
945
        }
946
        if ((u.bits.imm >> 5) & 0x1) {
947
            generateException(EXCEPTION_InstrIllegal, data);
948
        }
949
        data->npc = data->pc + 4;
950
    }
951
};
952
 
953
/**
954
 * @brief SRA arithmetic shift right
955
 */
956
class SRA : public IsaProcessor {
957
public:
958
    SRA() : IsaProcessor("SRA", "0100000??????????101?????0110011") {}
959
 
960
    virtual void exec(uint32_t *payload, CpuContextType *data) {
961
        ISA_R_type u;
962
        u.value = payload[0];
963
        data->regs[u.bits.rd] = static_cast<int64_t>(data->regs[u.bits.rs1])
964
                                >> (data->regs[u.bits.rs2] & 0x3F);
965
        data->npc = data->pc + 4;
966
    }
967
};
968
 
969
/**
970
 * @brief SRAW 32-bits arithmetic shift right (RV64I)
971
 */
972
class SRAW : public IsaProcessor {
973
public:
974
    SRAW() : IsaProcessor("SRAW", "0100000??????????101?????0111011") {}
975
 
976
    virtual void exec(uint32_t *payload, CpuContextType *data) {
977
        ISA_R_type u;
978
        u.value = payload[0];
979
        int32_t t1 = static_cast<int32_t>(data->regs[u.bits.rs1]);
980
        data->regs[u.bits.rd] =
981
            static_cast<int64_t>(t1 >> (data->regs[u.bits.rs2] & 0x1F));
982
        data->npc = data->pc + 4;
983
    }
984
};
985
 
986
 
987
/**
988
 * @brief SRAI is an arithmetic right shift.
989
 *
990
 * The original sign bit is copied into the vacanted upper bits.
991
 */
992
class SRAI : public IsaProcessor {
993
public:
994
    SRAI() : IsaProcessor("SRAI", "010000???????????101?????0010011") {}
995
 
996
    virtual void exec(uint32_t *payload, CpuContextType *data) {
997
        ISA_I_type u;
998
        u.value = payload[0];
999
        uint32_t shamt = u.bits.imm & 0x3f;
1000
        data->regs[u.bits.rd] =
1001
            static_cast<int64_t>(data->regs[u.bits.rs1]) >> shamt;
1002
        data->npc = data->pc + 4;
1003
    }
1004
};
1005
 
1006
/**
1007
 * @brief SRAIW arithmetic right shift (RV64I)
1008
 */
1009
class SRAIW : public IsaProcessor {
1010
public:
1011
    SRAIW() : IsaProcessor("SRAIW", "0100000??????????101?????0011011") {}
1012
 
1013
    virtual void exec(uint32_t *payload, CpuContextType *data) {
1014
        ISA_I_type u;
1015
        u.value = payload[0];
1016
        int32_t t1 = static_cast<int32_t>(data->regs[u.bits.rs1]);
1017
        uint32_t shamt = u.bits.imm & 0x1f;
1018
        data->regs[u.bits.rd] = static_cast<int64_t>(t1 >> shamt);
1019
        if ((u.bits.imm >> 5) & 0x1) {
1020
            generateException(EXCEPTION_InstrIllegal, data);
1021
        }
1022
        data->npc = data->pc + 4;
1023
    }
1024
};
1025
 
1026
 
1027
/**
1028
 * @brief SRL logical shift right
1029
 */
1030
class SRL : public IsaProcessor {
1031
public:
1032
    SRL() : IsaProcessor("SRL", "0000000??????????101?????0110011") {}
1033
 
1034
    virtual void exec(uint32_t *payload, CpuContextType *data) {
1035
        ISA_R_type u;
1036
        u.value = payload[0];
1037
        data->regs[u.bits.rd] =
1038
            data->regs[u.bits.rs1] >> (data->regs[u.bits.rs2] & 0x3F);
1039
        data->npc = data->pc + 4;
1040
    }
1041
};
1042
 
1043
/**
1044
 * @brief SRLI is a logical right shift (zeros are shifted into the upper bits)
1045
 */
1046
class SRLI : public IsaProcessor {
1047
public:
1048
    SRLI() : IsaProcessor("SRLI", "000000???????????101?????0010011") {}
1049
 
1050
    virtual void exec(uint32_t *payload, CpuContextType *data) {
1051
        ISA_I_type u;
1052
        u.value = payload[0];
1053
        uint32_t shamt = u.bits.imm & 0x3f;
1054
        data->regs[u.bits.rd] = data->regs[u.bits.rs1] >> shamt;
1055
        data->npc = data->pc + 4;
1056
    }
1057
};
1058
 
1059
/**
1060
 * @brief SRLIW logical right shift (RV64I)
1061
 */
1062
class SRLIW : public IsaProcessor {
1063
public:
1064
    SRLIW() : IsaProcessor("SRLIW", "0000000??????????101?????0011011") {}
1065
 
1066
    virtual void exec(uint32_t *payload, CpuContextType *data) {
1067
        ISA_I_type u;
1068
        u.value = payload[0];
1069
        uint32_t shamt = u.bits.imm & 0x1f;
1070
        data->regs[u.bits.rd] =
1071
            static_cast<uint32_t>(data->regs[u.bits.rs1]) >> shamt;
1072
        if ((u.bits.imm >> 5) & 0x1) {
1073
            generateException(EXCEPTION_InstrIllegal, data);
1074
        }
1075
        data->npc = data->pc + 4;
1076
    }
1077
};
1078
 
1079
/**
1080
 * @brief SRLW is a right shifts by register defined value (RV64I).
1081
 */
1082
class SRLW : public IsaProcessor {
1083
public:
1084
    SRLW() : IsaProcessor("SRLW", "0000000??????????101?????0111011") {}
1085
 
1086
    virtual void exec(uint32_t *payload, CpuContextType *data) {
1087
        ISA_R_type u;
1088
        u.value = payload[0];
1089
        data->regs[u.bits.rd] =
1090
            data->regs[u.bits.rs1] >> data->regs[u.bits.rs2];
1091
        data->regs[u.bits.rd] &= 0xFFFFFFFFLL;
1092
        if (data->regs[u.bits.rd] & (1LL << 31)) {
1093
            data->regs[u.bits.rd] |= EXT_SIGN_32;
1094
        }
1095
        data->npc = data->pc + 4;
1096
    }
1097
};
1098
 
1099
/**
1100
 * @brief STORE instructions (SD, SW, SH, SB)
1101
 *
1102
 * This instruction copies the value in register rs2 to memory.
1103
 * The effective byte address is obtained by adding register rs1 to the
1104
 * sign-extended 12-bit offset.
1105
 *   The SW, SH, and SB instructions store 32-bit, 16-bit, and 8-bit values
1106
 * from the low bits of register rs2 to memory.
1107
 */
1108
class SD : public IsaProcessor {
1109
public:
1110
    SD() : IsaProcessor("SD", "?????????????????011?????0100011") {}
1111
 
1112
    virtual void exec(uint32_t *payload, CpuContextType *data) {
1113
        Axi4TransactionType trans;
1114
        ISA_S_type u;
1115
        trans.source_idx = CFG_NASTI_MASTER_CACHED;
1116
        u.value = payload[0];
1117
        uint64_t off = (u.bits.imm11_5 << 5) | u.bits.imm4_0;
1118
        if (off & 0x800) {
1119
            off |= EXT_SIGN_12;
1120
        }
1121
        trans.action = MemAction_Write;
1122
        trans.xsize = 8;
1123
        trans.wstrb = (1 << trans.xsize) - 1;
1124
        trans.addr = data->regs[u.bits.rs1] + off;
1125
        trans.wpayload.b64[0] = data->regs[u.bits.rs2];
1126
        if (trans.addr & 0x7) {
1127
            generateException(EXCEPTION_LoadMisalign, data);
1128
        } else {
1129
            data->ibus->b_transport(&trans);
1130
            data->npc = data->pc + 4;
1131
        }
1132
        if (data->mem_trace_file) {
1133
            char tstr[512];
1134
            RISCV_sprintf(tstr, sizeof(tstr),
1135
                        "%08x: [%08x] <= %016" RV_PRI64 "x\n",
1136
                        static_cast<int>(data->pc),
1137
                        static_cast<int>(trans.addr), trans.wpayload.b64[0]);
1138
            (*data->mem_trace_file) << tstr;
1139
            data->mem_trace_file->flush();
1140
        }
1141
    }
1142
};
1143
 
1144
/**
1145
 * @brief Store rs2[31:0] to memory.
1146
 */
1147
class SW : public IsaProcessor {
1148
public:
1149
    SW() : IsaProcessor("SW", "?????????????????010?????0100011") {}
1150
 
1151
    virtual void exec(uint32_t *payload, CpuContextType *data) {
1152
        Axi4TransactionType trans;
1153
        trans.source_idx = CFG_NASTI_MASTER_CACHED;
1154
        trans.wpayload.b64[0] = 0;
1155
        ISA_S_type u;
1156
        u.value = payload[0];
1157
        uint64_t off = (u.bits.imm11_5 << 5) | u.bits.imm4_0;
1158
        if (off & 0x800) {
1159
            off |= EXT_SIGN_12;
1160
        }
1161
        trans.action = MemAction_Write;
1162
        trans.xsize = 4;
1163
        trans.wstrb = (1 << trans.xsize) - 1;
1164
        trans.addr = data->regs[u.bits.rs1] + off;
1165
        trans.wpayload.b64[0] = data->regs[u.bits.rs2];
1166
        if (trans.addr & 0x3) {
1167
            generateException(EXCEPTION_LoadMisalign, data);
1168
        } else {
1169
            data->ibus->b_transport(&trans);
1170
            data->npc = data->pc + 4;
1171
        }
1172
        if (data->mem_trace_file) {
1173
            char tstr[512];
1174
            RISCV_sprintf(tstr, sizeof(tstr),
1175
                        "%08x: [%08x] <= %016" RV_PRI64 "x\n",
1176
                        static_cast<int>(data->pc),
1177
                        static_cast<int>(trans.addr),
1178
                        static_cast<uint64_t>(trans.wpayload.b32[0]));
1179
            (*data->mem_trace_file) << tstr;
1180
            data->mem_trace_file->flush();
1181
        }
1182
    }
1183
};
1184
 
1185
/**
1186
 * @brief Store rs2[15:0] to memory.
1187
 */
1188
class SH : public IsaProcessor {
1189
public:
1190
    SH() : IsaProcessor("SH", "?????????????????001?????0100011") {}
1191
 
1192
    virtual void exec(uint32_t *payload, CpuContextType *data) {
1193
        Axi4TransactionType trans;
1194
        trans.source_idx = CFG_NASTI_MASTER_CACHED;
1195
        trans.wpayload.b64[0] = 0;
1196
        ISA_S_type u;
1197
        u.value = payload[0];
1198
        uint64_t off = (u.bits.imm11_5 << 5) | u.bits.imm4_0;
1199
        if (off & 0x800) {
1200
            off |= EXT_SIGN_12;
1201
        }
1202
        trans.action = MemAction_Write;
1203
        trans.xsize = 2;
1204
        trans.wstrb = (1 << trans.xsize) - 1;
1205
        trans.addr = data->regs[u.bits.rs1] + off;
1206
        trans.wpayload.b64[0] = data->regs[u.bits.rs2] & 0xFFFF;
1207
        if (trans.addr & 0x1) {
1208
            generateException(EXCEPTION_LoadMisalign, data);
1209
        } else {
1210
            data->ibus->b_transport(&trans);
1211
            data->npc = data->pc + 4;
1212
        }
1213
        if (data->mem_trace_file) {
1214
            char tstr[512];
1215
            RISCV_sprintf(tstr, sizeof(tstr),
1216
                        "%08x: [%08x] <= %016" RV_PRI64 "x\n",
1217
                        static_cast<int>(data->pc),
1218
                        static_cast<int>(trans.addr),
1219
                        static_cast<uint64_t>(trans.wpayload.b16[0]));
1220
            (*data->mem_trace_file) << tstr;
1221
            data->mem_trace_file->flush();
1222
        }
1223
    }
1224
};
1225
 
1226
/**
1227
 * @brief Store rs2[7:0] to memory.
1228
 */
1229
class SB : public IsaProcessor {
1230
public:
1231
    SB() : IsaProcessor("SB", "?????????????????000?????0100011") {}
1232
 
1233
    virtual void exec(uint32_t *payload, CpuContextType *data) {
1234
        Axi4TransactionType trans;
1235
        trans.source_idx = CFG_NASTI_MASTER_CACHED;
1236
        trans.wpayload.b64[0] = 0;
1237
        ISA_S_type u;
1238
        u.value = payload[0];
1239
        uint64_t off = (u.bits.imm11_5 << 5) | u.bits.imm4_0;
1240
        if (off & 0x800) {
1241
            off |= EXT_SIGN_12;
1242
        }
1243
        trans.action = MemAction_Write;
1244
        trans.xsize = 1;
1245
        trans.wstrb = (1 << trans.xsize) - 1;
1246
        trans.addr = data->regs[u.bits.rs1] + off;
1247
        trans.wpayload.b64[0] = data->regs[u.bits.rs2] & 0xFF;
1248
        data->ibus->b_transport(&trans);
1249
        data->npc = data->pc + 4;
1250
        if (data->mem_trace_file) {
1251
            char tstr[512];
1252
            RISCV_sprintf(tstr, sizeof(tstr),
1253
                        "%08x: [%08x] <= %016" RV_PRI64 "x\n",
1254
                        static_cast<int>(data->pc),
1255
                        static_cast<int>(trans.addr),
1256
                        static_cast<uint64_t>(trans.wpayload.b8[0]));
1257
            (*data->mem_trace_file) << tstr;
1258
            data->mem_trace_file->flush();
1259
        }
1260
    }
1261
};
1262
 
1263
/**
1264
 * @brief Subtruction. Overflows are ignored
1265
 */
1266
class SUB : public IsaProcessor {
1267
public:
1268
    SUB() : IsaProcessor("SUB", "0100000??????????000?????0110011") {}
1269
 
1270
    virtual void exec(uint32_t *payload, CpuContextType *data) {
1271
        ISA_R_type u;
1272
        u.value = payload[0];
1273
        data->regs[u.bits.rd] = data->regs[u.bits.rs1] - data->regs[u.bits.rs2];
1274
        data->npc = data->pc + 4;
1275
    }
1276
};
1277
 
1278
/**
1279
 * @brief Substruct registers with sign extending (RV64I)
1280
 *
1281
 * SUBW is RV64I-only instructions that are defined analogously to
1282
 * SUB but operate on 32-bit values and produce signed 32-bit results.
1283
 * Overflows are ignored, and the low 32-bits of the result is sign-extended
1284
 * to 64-bits and written to the destination register.
1285
 */
1286
class SUBW : public IsaProcessor {
1287
public:
1288
    SUBW() : IsaProcessor("SUBW", "0100000??????????000?????0111011") {}
1289
 
1290
    virtual void exec(uint32_t *payload, CpuContextType *data) {
1291
        ISA_R_type u;
1292
        u.value = payload[0];
1293
 
1294
        data->regs[u.bits.rd] =
1295
            (data->regs[u.bits.rs1] - data->regs[u.bits.rs2]) & 0xFFFFFFFFLL;
1296
        if (data->regs[u.bits.rd] & (1LL << 31)) {
1297
            data->regs[u.bits.rd] |= EXT_SIGN_32;
1298
        }
1299
        data->npc = data->pc + 4;
1300
    }
1301
};
1302
 
1303
/**
1304
 * @brief XOR bitwise operation
1305
 */
1306
class XOR : public IsaProcessor {
1307
public:
1308
    XOR() : IsaProcessor("XOR", "0000000??????????100?????0110011") {}
1309
 
1310
    virtual void exec(uint32_t *payload, CpuContextType *data) {
1311
        ISA_R_type u;
1312
        u.value = payload[0];
1313
        data->regs[u.bits.rd] =
1314
                data->regs[u.bits.rs1] ^ data->regs[u.bits.rs2];
1315
        data->npc = data->pc + 4;
1316
    }
1317
};
1318
 
1319
/**
1320
 * @brief XOR on register rs1 and the sign-extended 12-bit immediate.
1321
 *
1322
 * XORI rd, rs1, -1 performs a bitwise logical inversion of register rs1
1323
 * (assembler pseudo-instruction NOT rd, rs).
1324
 */
1325
class XORI : public IsaProcessor {
1326
public:
1327
    XORI() : IsaProcessor("XORI", "?????????????????100?????0010011") {}
1328
 
1329
    virtual void exec(uint32_t *payload, CpuContextType *data) {
1330
        ISA_I_type u;
1331
        u.value = payload[0];
1332
 
1333
        uint64_t imm = u.bits.imm;
1334
        if (imm & 0x800) {
1335
            imm |= EXT_SIGN_12;
1336
        }
1337
        data->regs[u.bits.rd] = data->regs[u.bits.rs1] ^ imm;
1338
        data->npc = data->pc + 4;
1339
    }
1340
};
1341
 
1342
void addIsaUserRV64I(CpuContextType *data, AttributeType *out) {
1343
    addSupportedInstruction(new ADD, out);
1344
    addSupportedInstruction(new ADDI, out);
1345
    addSupportedInstruction(new ADDIW, out);
1346
    addSupportedInstruction(new ADDW, out);
1347
    addSupportedInstruction(new AND, out);
1348
    addSupportedInstruction(new ANDI, out);
1349
    addSupportedInstruction(new AUIPC, out);
1350
    addSupportedInstruction(new BEQ, out);
1351
    addSupportedInstruction(new BGE, out);
1352
    addSupportedInstruction(new BGEU, out);
1353
    addSupportedInstruction(new BLT, out);
1354
    addSupportedInstruction(new BLTU, out);
1355
    addSupportedInstruction(new BNE, out);
1356
    addSupportedInstruction(new JAL, out);
1357
    addSupportedInstruction(new JALR, out);
1358
    addSupportedInstruction(new LD, out);
1359
    addSupportedInstruction(new LW, out);
1360
    addSupportedInstruction(new LWU, out);
1361
    addSupportedInstruction(new LH, out);
1362
    addSupportedInstruction(new LHU, out);
1363
    addSupportedInstruction(new LB, out);
1364
    addSupportedInstruction(new LBU, out);
1365
    addSupportedInstruction(new LUI, out);
1366
    addSupportedInstruction(new OR, out);
1367
    addSupportedInstruction(new ORI, out);
1368
    addSupportedInstruction(new SLL, out);
1369
    addSupportedInstruction(new SLLI, out);
1370
    addSupportedInstruction(new SLLIW, out);
1371
    addSupportedInstruction(new SLLW, out);
1372
    addSupportedInstruction(new SLT, out);
1373
    addSupportedInstruction(new SLTI, out);
1374
    addSupportedInstruction(new SLTU, out);
1375
    addSupportedInstruction(new SLTIU, out);
1376
    addSupportedInstruction(new SRA, out);
1377
    addSupportedInstruction(new SRAI, out);
1378
    addSupportedInstruction(new SRAIW, out);
1379
    addSupportedInstruction(new SRAW, out);
1380
    addSupportedInstruction(new SRL, out);
1381
    addSupportedInstruction(new SRLI, out);
1382
    addSupportedInstruction(new SRLIW, out);
1383
    addSupportedInstruction(new SRLW, out);
1384
    addSupportedInstruction(new SUB, out);
1385
    addSupportedInstruction(new SUBW, out);
1386
    addSupportedInstruction(new SD, out);
1387
    addSupportedInstruction(new SW, out);
1388
    addSupportedInstruction(new SH, out);
1389
    addSupportedInstruction(new SB, out);
1390
    addSupportedInstruction(new XOR, out);
1391
    addSupportedInstruction(new XORI, out);
1392
 
1393
    /** Base[XLEN-1:XLEN-2]
1394
     *      1 = 32
1395
     *      2 = 64
1396
     *      3 = 128
1397
     */
1398
    data->csr[CSR_misa] = 0x8000000000000000LL;
1399
    data->csr[CSR_misa] |= (1LL << ('I' - 'A'));
1400
}
1401
 
1402
/**
1403
 * When a trap is taken, the stack is pushed to the left and PRV is set to the
1404
 * privilege mode of the activated trap handler with
1405
 * IE=0.
1406
 *
1407
 * By default, all traps at any privilege level are handled in machine mode,
1408
 * though a machine-mode  * handler can quickly redirect traps back to the
1409
 * appropriate level using mrts and mrth instructions (Section 3.2.2).
1410
 * To increase performance, implementations can provide individual read/write
1411
 * bits within mtdeleg to indicate that certain traps should be processed
1412
 * directly by a lower privilege level.
1413
 *
1414
 * The machine trap delegation register (mtdeleg) is an XLEN-bit read/write
1415
 * register that must be implemented, but which can contain a read-only value
1416
 * of zero, indicating that hardware will always direct all traps to machine
1417
 * mode.
1418
 */
1419
void generateException(uint64_t code, CpuContextType *data) {
1420
    csr_mcause_type cause;
1421
    cause.value     = 0;
1422
    cause.bits.irq  = 0;
1423
    cause.bits.code = code;
1424
    data->csr[CSR_mcause] = cause.value;
1425
    data->exception |= 1LL << code;
1426
}
1427
 
1428
void generateInterrupt(uint64_t code, CpuContextType *data) {
1429
    csr_mcause_type cause;
1430
    cause.value     = 0;
1431
    cause.bits.irq  = 1;
1432
    cause.bits.code = code;
1433
    data->csr[CSR_mcause] = cause.value;
1434
    data->interrupt = 1;
1435
}
1436
 
1437
}  // namespace debugger

powered by: WebSVN 2.1.0

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