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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [cpu_fnc_plugin/] [riscv-ext-m.cpp] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 sergeykhbr
/**
2
 * @file
3
 * @copyright  Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
5
 * @brief      RISC-V extension-M.
6
 */
7
 
8
#include "api_utils.h"
9
#include "riscv-isa.h"
10
#include "cpu_riscv_func.h"
11
 
12
namespace debugger {
13
 
14
/**
15
 * @brief The DIV signed division
16
 */
17
class DIV : public RiscvInstruction {
18
 public:
19
    DIV(CpuRiver_Functional *icpu)
20
        : RiscvInstruction(icpu, "DIV", "0000001??????????100?????0110011") {}
21
 
22
    virtual int exec(Reg64Type *payload) {
23
        ISA_R_type u;
24
        u.value = payload->buf32[0];
25
        if (R[u.bits.rs2]) {
26
            R[u.bits.rd] = static_cast<int64_t>(R[u.bits.rs1])
27
                 / static_cast<int64_t>(R[u.bits.rs2]);
28
        } else {
29
            R[u.bits.rd] = 0;
30
        }
31
        return 4;
32
    }
33
};
34
 
35
/**
36
 * @brief DIVU unsigned division
37
 */
38
class DIVU : public RiscvInstruction {
39
 public:
40
    DIVU(CpuRiver_Functional *icpu)
41
        : RiscvInstruction(icpu, "DIVU", "0000001??????????101?????0110011") {}
42
 
43
    virtual int exec(Reg64Type *payload) {
44
        ISA_R_type u;
45
        u.value = payload->buf32[0];
46
        if (R[u.bits.rs2]) {
47
            R[u.bits.rd] = R[u.bits.rs1] / R[u.bits.rs2];
48
        } else {
49
            R[u.bits.rd] = 0;
50
        }
51
        return 4;
52
    }
53
};
54
 
55
/**
56
 * @brief DIVUW 32-bits unsigned division (RV64I)
57
 */
58
class DIVUW : public RiscvInstruction {
59
 public:
60
    DIVUW(CpuRiver_Functional *icpu) :
61
        RiscvInstruction(icpu, "DIVUW", "0000001??????????101?????0111011") {}
62
 
63
    virtual int exec(Reg64Type *payload) {
64
        ISA_R_type u;
65
        u.value = payload->buf32[0];
66
        if (static_cast<uint32_t>(R[u.bits.rs2])) {
67
            R[u.bits.rd] =
68
                static_cast<uint32_t>(R[u.bits.rs1]) /
69
                static_cast<uint32_t>(R[u.bits.rs2]);
70
        } else {
71
            R[u.bits.rd] = 0;
72
        }
73
        return 4;
74
    }
75
};
76
 
77
/**
78
 * @brief DIVW 32-bits signed division (RV64I)
79
 */
80
class DIVW : public RiscvInstruction {
81
 public:
82
    DIVW(CpuRiver_Functional *icpu)
83
        : RiscvInstruction(icpu, "DIVW", "0000001??????????100?????0111011") {}
84
 
85
    virtual int exec(Reg64Type *payload) {
86
        ISA_R_type u;
87
        u.value = payload->buf32[0];
88
        int32_t divident = static_cast<int32_t>(R[u.bits.rs1]);
89
        int32_t divisor = static_cast<int32_t>(R[u.bits.rs2]);
90
        if (divisor) {
91
            R[u.bits.rd] = static_cast<int64_t>(divident / divisor);
92
        } else {
93
            R[u.bits.rd] = 0;
94
        }
95
        return 4;
96
    }
97
};
98
 
99
/**
100
 * @brief The MUL signed multiplication
101
 *
102
 * MUL performs an XLEN-bit XLEN-bit multiplication and places the lower XLEN
103
 * bits in the destination register.
104
 */
105
class MUL : public RiscvInstruction {
106
 public:
107
    MUL(CpuRiver_Functional *icpu)
108
        : RiscvInstruction(icpu, "MUL", "0000001??????????000?????0110011") {}
109
 
110
    virtual int exec(Reg64Type *payload) {
111
        ISA_R_type u;
112
        u.value = payload->buf32[0];
113
        R[u.bits.rd] = static_cast<int64_t>(R[u.bits.rs1])
114
                * static_cast<int64_t>(R[u.bits.rs2]);
115
        return 4;
116
    }
117
};
118
 
119
/**
120
 * @brief The MULW 32-bits signed multiplication (RV64I)
121
 *
122
 * MULW is only valid for RV64, and multiplies the lower 32 bits of the source
123
 * registers, placing the sign-extension of the lower 32 bits of the result
124
 * into the destination register. MUL can be used to obtain the upper 32 bits
125
 * of the 64-bit product, but signed arguments must be proper 32-bit signed
126
 * values, whereas unsigned arguments must have their upper 32 bits clear.
127
 */
128
class MULW : public RiscvInstruction {
129
 public:
130
    MULW(CpuRiver_Functional *icpu)
131
        : RiscvInstruction(icpu, "MULW", "0000001??????????000?????0111011") {}
132
 
133
    virtual int exec(Reg64Type *payload) {
134
        ISA_R_type u;
135
        u.value = payload->buf32[0];
136
        int32_t m1 = static_cast<int32_t>(R[u.bits.rs1]);
137
        int32_t m2 = static_cast<int32_t>(R[u.bits.rs2]);
138
 
139
        R[u.bits.rd] = static_cast<int64_t>(m1 * m2);
140
        if (R[u.bits.rd] & (1LL << 31)) {
141
            R[u.bits.rd] |= EXT_SIGN_32;
142
        }
143
        return 4;
144
    }
145
};
146
 
147
/**
148
 * @brief The REM (remainder of the corresponding signed division operation)
149
 */
150
class REM : public RiscvInstruction {
151
public:
152
    REM(CpuRiver_Functional *icpu)
153
        : RiscvInstruction(icpu, "REM", "0000001??????????110?????0110011") {}
154
 
155
    virtual int exec(Reg64Type *payload) {
156
        ISA_R_type u;
157
        u.value = payload->buf32[0];
158
        R[u.bits.rd] = static_cast<int64_t>(R[u.bits.rs1])
159
             % static_cast<int64_t>(R[u.bits.rs2]);
160
        return 4;
161
    }
162
};
163
 
164
/**
165
 * @brief The REMU (remainder of the corresponding unsgined division operation)
166
 */
167
class REMU : public RiscvInstruction {
168
public:
169
    REMU(CpuRiver_Functional *icpu)
170
        : RiscvInstruction(icpu, "REMU", "0000001??????????111?????0110011") {}
171
 
172
    virtual int exec(Reg64Type *payload) {
173
        ISA_R_type u;
174
        u.value = payload->buf32[0];
175
        R[u.bits.rd] = R[u.bits.rs1] % R[u.bits.rs2];
176
        return 4;
177
    }
178
};
179
 
180
/**
181
 * @brief REMW signed reminder operation
182
 *
183
 * REMW and REMUW instructions are only valid
184
 * for RV64, and provide the corresponding signed and unsigned remainder
185
 * operations respectively.
186
 * Both REMW and REMUW sign-extend the 32-bit result to 64 bits.
187
 */
188
class REMW : public RiscvInstruction {
189
public:
190
    REMW(CpuRiver_Functional *icpu)
191
        : RiscvInstruction(icpu, "REMW", "0000001??????????110?????0111011") {}
192
 
193
    virtual int exec(Reg64Type *payload) {
194
        ISA_R_type u;
195
        int32_t tmp;
196
        u.value = payload->buf32[0];
197
        tmp = static_cast<int32_t>(R[u.bits.rs1])
198
            % static_cast<int32_t>(R[u.bits.rs2]);
199
        R[u.bits.rd] = static_cast<uint64_t>(static_cast<int64_t>(tmp));
200
        return 4;
201
    }
202
};
203
 
204
class REMUW : public RiscvInstruction {
205
public:
206
    REMUW(CpuRiver_Functional *icpu) :
207
        RiscvInstruction(icpu, "REMUW", "0000001??????????111?????0111011") {}
208
 
209
    virtual int exec(Reg64Type *payload) {
210
        ISA_R_type u;
211
        uint32_t tmp;
212
        u.value = payload->buf32[0];
213
        tmp = static_cast<uint32_t>(R[u.bits.rs1])
214
            % static_cast<uint32_t>(R[u.bits.rs2]);
215
        R[u.bits.rd] = static_cast<uint64_t>(static_cast<int64_t>(tmp));
216
        return 4;
217
    }
218
};
219
 
220
void CpuRiver_Functional::addIsaExtensionM() {
221
    addSupportedInstruction(new DIV(this));
222
    addSupportedInstruction(new DIVU(this));
223
    addSupportedInstruction(new DIVUW(this));
224
    addSupportedInstruction(new DIVW(this));
225
    addSupportedInstruction(new MUL(this));
226
    addSupportedInstruction(new MULW(this));
227
    addSupportedInstruction(new REM(this));
228
    addSupportedInstruction(new REMU(this));
229
    addSupportedInstruction(new REMW(this));
230
    addSupportedInstruction(new REMUW(this));
231
 
232
    // TODO
233
    /*
234
    addInstr("MULH", "0000001??????????001?????0110011", NULL, out);
235
    addInstr("MULHSU", "0000001??????????010?????0110011", NULL, out);
236
    addInstr("MULHU", "0000001??????????011?????0110011", NULL, out);
237
    */
238
 
239
    uint64_t isa = portCSR_.read(CSR_misa).val;
240
    portCSR_.write(CSR_misa, isa | (1LL << ('M' - 'A')));
241
}
242
 
243
}  // namespace debugger

powered by: WebSVN 2.1.0

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