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 2

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

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

powered by: WebSVN 2.1.0

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