blob: 775cf1ffc96301bdea194f9a63b37b25ecb67788 [file] [log] [blame]
Alessandro Gatti8338f662024-06-08 11:00:08 +02001/*
2 * This file is part of the MicroPython project, https://micropython.org/
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2024 Alessandro Gatti
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
27#ifndef MICROPY_INCLUDED_PY_ASMRV32_H
28#define MICROPY_INCLUDED_PY_ASMRV32_H
29
30#include <assert.h>
31
32#include "py/asmbase.h"
33#include "py/emit.h"
34#include "py/misc.h"
35#include "py/persistentcode.h"
36
37#define ASM_RV32_REG_X0 (0) // Zero
38#define ASM_RV32_REG_X1 (1) // RA
39#define ASM_RV32_REG_X2 (2) // SP
40#define ASM_RV32_REG_X3 (3) // GP
41#define ASM_RV32_REG_X4 (4) // TP
42#define ASM_RV32_REG_X5 (5) // T0
43#define ASM_RV32_REG_X6 (6) // T1
44#define ASM_RV32_REG_X7 (7) // T2
45#define ASM_RV32_REG_X8 (8) // S0
46#define ASM_RV32_REG_X9 (9) // S1
47#define ASM_RV32_REG_X10 (10) // A0
48#define ASM_RV32_REG_X11 (11) // A1
49#define ASM_RV32_REG_X12 (12) // A2
50#define ASM_RV32_REG_X13 (13) // A3
51#define ASM_RV32_REG_X14 (14) // A4
52#define ASM_RV32_REG_X15 (15) // A5
53#define ASM_RV32_REG_X16 (16) // A6
54#define ASM_RV32_REG_X17 (17) // A7
55#define ASM_RV32_REG_X18 (18) // S2
56#define ASM_RV32_REG_X19 (19) // S3
57#define ASM_RV32_REG_X20 (20) // S4
58#define ASM_RV32_REG_X21 (21) // S5
59#define ASM_RV32_REG_X22 (22) // S6
60#define ASM_RV32_REG_X23 (23) // S7
61#define ASM_RV32_REG_X24 (24) // S8
62#define ASM_RV32_REG_X25 (25) // S9
63#define ASM_RV32_REG_X26 (26) // S10
64#define ASM_RV32_REG_X27 (27) // S11
65#define ASM_RV32_REG_X28 (28) // T3
66#define ASM_RV32_REG_X29 (29) // T4
67#define ASM_RV32_REG_X30 (30) // T5
68#define ASM_RV32_REG_X31 (31) // T6
69
70// Alternate register names.
71
72#define ASM_RV32_REG_ZERO (ASM_RV32_REG_X0)
73#define ASM_RV32_REG_RA (ASM_RV32_REG_X1)
74#define ASM_RV32_REG_SP (ASM_RV32_REG_X2)
75#define ASM_RV32_REG_GP (ASM_RV32_REG_X3)
76#define ASM_RV32_REG_TP (ASM_RV32_REG_X4)
77#define ASM_RV32_REG_T0 (ASM_RV32_REG_X5)
78#define ASM_RV32_REG_T1 (ASM_RV32_REG_X6)
79#define ASM_RV32_REG_T2 (ASM_RV32_REG_X7)
80#define ASM_RV32_REG_A0 (ASM_RV32_REG_X10)
81#define ASM_RV32_REG_A1 (ASM_RV32_REG_X11)
82#define ASM_RV32_REG_A2 (ASM_RV32_REG_X12)
83#define ASM_RV32_REG_A3 (ASM_RV32_REG_X13)
84#define ASM_RV32_REG_A4 (ASM_RV32_REG_X14)
85#define ASM_RV32_REG_A5 (ASM_RV32_REG_X15)
86#define ASM_RV32_REG_A6 (ASM_RV32_REG_X16)
87#define ASM_RV32_REG_A7 (ASM_RV32_REG_X17)
88#define ASM_RV32_REG_T3 (ASM_RV32_REG_X28)
89#define ASM_RV32_REG_T4 (ASM_RV32_REG_X29)
90#define ASM_RV32_REG_T5 (ASM_RV32_REG_X30)
91#define ASM_RV32_REG_T6 (ASM_RV32_REG_X31)
92#define ASM_RV32_REG_FP (ASM_RV32_REG_X8)
93#define ASM_RV32_REG_S0 (ASM_RV32_REG_X8)
94#define ASM_RV32_REG_S1 (ASM_RV32_REG_X9)
95#define ASM_RV32_REG_S2 (ASM_RV32_REG_X18)
96#define ASM_RV32_REG_S3 (ASM_RV32_REG_X19)
97#define ASM_RV32_REG_S4 (ASM_RV32_REG_X20)
98#define ASM_RV32_REG_S5 (ASM_RV32_REG_X21)
99#define ASM_RV32_REG_S6 (ASM_RV32_REG_X22)
100#define ASM_RV32_REG_S7 (ASM_RV32_REG_X23)
101#define ASM_RV32_REG_S8 (ASM_RV32_REG_X24)
102#define ASM_RV32_REG_S9 (ASM_RV32_REG_X25)
103#define ASM_RV32_REG_S10 (ASM_RV32_REG_X26)
104#define ASM_RV32_REG_S11 (ASM_RV32_REG_X27)
105
106typedef struct _asm_rv32_t {
107 // Opaque emitter state.
108 mp_asm_base_t base;
109 // Which registers are tainted and need saving/restoring.
110 mp_uint_t saved_registers_mask;
111 // How many locals must be stored on the stack.
112 mp_uint_t locals_count;
113 // The computed function stack size.
114 mp_uint_t stack_size;
115 // The stack offset where stack-based locals start to be stored.
116 mp_uint_t locals_stack_offset;
117} asm_rv32_t;
118
119void asm_rv32_entry(asm_rv32_t *state, mp_uint_t locals);
120void asm_rv32_exit(asm_rv32_t *state);
121void asm_rv32_end_pass(asm_rv32_t *state);
122
123////////////////////////////////////////////////////////////////////////////////
124
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200125#define RV32_ENCODE_TYPE_B(op, ft3, rs1, rs2, imm) \
126 ((op & 0x7F) | ((ft3 & 0x07) << 12) | ((imm & 0x800) >> 4) | \
127 ((imm & 0x1E) << 7) | ((rs1 & 0x1F) << 15) | ((rs2 & 0x1F) << 20) | \
128 ((imm & 0x7E0) << 20) | ((imm & 0x1000) << 19))
Alessandro Gatti8338f662024-06-08 11:00:08 +0200129
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200130#define RV32_ENCODE_TYPE_I(op, ft3, rd, rs, imm) \
131 ((op & 0x7F) | ((rd & 0x1F) << 7) | ((ft3 & 0x07) << 12) | \
132 ((rs & 0x1F) << 15) | ((imm & 0xFFF) << 20))
Alessandro Gatti8338f662024-06-08 11:00:08 +0200133
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200134#define RV32_ENCODE_TYPE_J(op, rd, imm) \
135 ((op & 0x7F) | ((rd & 0x1F) << 7) | (imm & 0xFF000) | \
136 ((imm & 0x800) << 9) | ((imm & 0x7FE) << 20) | ((imm & 0x100000) << 11))
Alessandro Gatti8338f662024-06-08 11:00:08 +0200137
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200138#define RV32_ENCODE_TYPE_R(op, ft3, ft7, rd, rs1, rs2) \
139 ((op & 0x7F) | ((rd & 0x1F) << 7) | ((ft3 & 0x07) << 12) | \
140 ((rs1 & 0x1F) << 15) | ((rs2 & 0x1F) << 20) | ((ft7 & 0x7F) << 25))
Alessandro Gatti8338f662024-06-08 11:00:08 +0200141
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200142#define RV32_ENCODE_TYPE_S(op, ft3, rs1, rs2, imm) \
143 ((op & 0x7F) | ((imm & 0x1F) << 7) | ((ft3 & 0x07) << 12) | \
144 ((rs1 & 0x1F) << 15) | ((rs2 & 0x1F) << 20) | ((imm & 0xFE0) << 20))
Alessandro Gatti8338f662024-06-08 11:00:08 +0200145
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200146#define RV32_ENCODE_TYPE_U(op, rd, imm) \
147 ((op & 0x7F) | ((rd & 0x1F) << 7) | (imm & 0xFFFFF000))
Alessandro Gatti8338f662024-06-08 11:00:08 +0200148
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200149#define RV32_ENCODE_TYPE_CB(op, ft3, rs, imm) \
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200150 ((op & 0x03) | ((ft3 & 0x07) << 13) | ((rs & 0x07) << 7) | \
151 (((imm) & 0x100) << 4) | (((imm) & 0xC0) >> 1) | (((imm) & 0x20) >> 3) | \
152 (((imm) & 0x18) << 7) | (((imm) & 0x06) << 2))
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200153
Alessandro Gatti8338f662024-06-08 11:00:08 +0200154#define RV32_ENCODE_TYPE_CI(op, ft3, rd, imm) \
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200155 ((op & 0x03) | ((ft3 & 0x07) << 13) | ((rd & 0x1F) << 7) | \
156 (((imm) & 0x20) << 7) | (((imm) & 0x1F) << 2))
Alessandro Gatti8338f662024-06-08 11:00:08 +0200157
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200158#define RV32_ENCODE_TYPE_CIW(op, ft3, rd, imm) \
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200159 ((op & 0x03) | ((ft3 & 0x07) << 13) | ((rd & 0x07) << 2) | \
160 ((imm & 0x3C0) << 1) | ((imm & 0x30) << 7) | \
161 ((imm & 0x08) << 2) | ((imm & 0x04) << 4))
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200162
Alessandro Gatti8338f662024-06-08 11:00:08 +0200163#define RV32_ENCODE_TYPE_CJ(op, ft3, imm) \
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200164 ((op & 0x03) | ((ft3 & 0x07) << 13) | ((imm & 0x0E) << 2) | \
165 ((imm & 0x300) << 1) | ((imm & 0x800) << 1) | ((imm & 0x400) >> 2) | \
166 ((imm & 0x80) >> 1) | ((imm & 0x40) << 1) | ((imm & 0x20) >> 3) | \
167 ((imm & 0x10) << 7))
Alessandro Gatti8338f662024-06-08 11:00:08 +0200168
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200169#define RV32_ENCODE_TYPE_CL(op, ft3, rd, rs, imm) \
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200170 ((op & 0x03) | ((ft3 & 0x07) << 13) | ((rd & 0x07) << 2) | \
171 ((rs & 0x07) << 7) | ((imm & 0x40) >> 1) | ((imm & 0x38) << 7) | \
172 ((imm & 0x04) << 4))
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200173
Alessandro Gatti8338f662024-06-08 11:00:08 +0200174#define RV32_ENCODE_TYPE_CR(op, ft4, rs1, rs2) \
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200175 ((op & 0x03) | ((rs2 & 0x1F) << 2) | ((rs1 & 0x1F) << 7) | ((ft4 & 0x0F) << 12))
Alessandro Gatti8338f662024-06-08 11:00:08 +0200176
177#define RV32_ENCODE_TYPE_CSS(op, ft3, rs, imm) \
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200178 ((op & 0x03) | ((ft3 & 0x07) << 13) | ((rs & 0x1F) << 2) | ((imm) & 0x3F) << 7)
Alessandro Gatti8338f662024-06-08 11:00:08 +0200179
180void asm_rv32_emit_word_opcode(asm_rv32_t *state, mp_uint_t opcode);
181void asm_rv32_emit_halfword_opcode(asm_rv32_t *state, mp_uint_t opcode);
182
183// ADD RD, RS1, RS2
184static inline void asm_rv32_opcode_add(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) {
185 // R: 0000000 ..... ..... 000 ..... 0110011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200186 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x00, 0x00, rd, rs1, rs2));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200187}
188
189// ADDI RD, RS, IMMEDIATE
190static inline void asm_rv32_opcode_addi(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t immediate) {
191 // I: ............ ..... 000 ..... 0010011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200192 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x13, 0x00, rd, rs, immediate));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200193}
194
195// AND RD, RS1, RS2
196static inline void asm_rv32_opcode_and(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) {
197 // R: 0000000 ..... ..... 111 ..... 0110011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200198 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x07, 0x00, rd, rs1, rs2));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200199}
200
201// AUIPC RD, offset
202static inline void asm_rv32_opcode_auipc(asm_rv32_t *state, mp_uint_t rd, mp_int_t offset) {
203 // U: .................... ..... 0010111
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200204 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_U(0x17, rd, offset));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200205}
206
207// BEQ RS1, RS2, OFFSET
208static inline void asm_rv32_opcode_beq(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_int_t offset) {
209 // B: . ...... ..... ..... 000 .... . 1100011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200210 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_B(0x63, 0x00, rs1, rs2, offset));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200211}
212
213// BNE RS1, RS2, OFFSET
214static inline void asm_rv32_opcode_bne(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_int_t offset) {
215 // B: . ...... ..... ..... 001 .... . 1100011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200216 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_B(0x63, 0x01, rs1, rs2, offset));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200217}
218
219// C.ADD RD, RS
220static inline void asm_rv32_opcode_cadd(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs) {
221 // CR: 1001 ..... ..... 10
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200222 asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CR(0x02, 0x09, rd, rs));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200223}
224
225// C.ADDI RD, IMMEDIATE
226static inline void asm_rv32_opcode_caddi(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate) {
227 // CI: 000 . ..... ..... 01
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200228 asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CI(0x01, 0x00, rd, immediate));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200229}
230
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200231// C.ADDI4SPN RD', IMMEDIATE
232static inline void asm_rv32_opcode_caddi4spn(asm_rv32_t *state, mp_uint_t rd, mp_uint_t immediate) {
233 // CIW: 000 ........ ... 00
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200234 asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CIW(0x00, 0x00, rd, immediate));
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200235}
236
237// C.BEQZ RS', IMMEDIATE
238static inline void asm_rv32_opcode_cbeqz(asm_rv32_t *state, mp_uint_t rs, mp_int_t offset) {
239 // CB: 110 ... ... ..... 01
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200240 asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CB(0x01, 0x06, rs, offset));
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200241}
242
243// C.BNEZ RS', IMMEDIATE
244static inline void asm_rv32_opcode_cbnez(asm_rv32_t *state, mp_uint_t rs, mp_int_t offset) {
245 // CB: 111 ... ... ..... 01
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200246 asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CB(0x01, 0x07, rs, offset));
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200247}
248
Alessandro Gatti8338f662024-06-08 11:00:08 +0200249// C.J OFFSET
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200250static inline void asm_rv32_opcode_cj(asm_rv32_t *state, mp_int_t offset) {
Alessandro Gatti8338f662024-06-08 11:00:08 +0200251 // CJ: 101 ........... 01
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200252 asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CJ(0x01, 0x05, offset));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200253}
254
255// C.JALR RS
256static inline void asm_rv32_opcode_cjalr(asm_rv32_t *state, mp_uint_t rs) {
257 // CR: 1001 ..... 00000 10
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200258 asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CR(0x02, 0x09, rs, 0));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200259}
260
261// C.JR RS
262static inline void asm_rv32_opcode_cjr(asm_rv32_t *state, mp_uint_t rs) {
263 // CR: 1000 ..... 00000 10
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200264 asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CR(0x02, 0x08, rs, 0));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200265}
266
267// C.LI RD, IMMEDIATE
268static inline void asm_rv32_opcode_cli(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate) {
269 // CI: 010 . ..... ..... 01
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200270 asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CI(0x01, 0x02, rd, immediate));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200271}
272
273// C.LUI RD, IMMEDIATE
274static inline void asm_rv32_opcode_clui(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate) {
275 // CI: 011 . ..... ..... 01
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200276 asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CI(0x01, 0x03, rd, immediate >> 12));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200277}
278
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200279// C.LW RD', OFFSET(RS')
280static inline void asm_rv32_opcode_clw(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) {
281 // CL: 010 ... ... .. ... 00
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200282 asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CL(0x00, 0x02, rd, rs, offset));
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200283}
284
Alessandro Gatti8338f662024-06-08 11:00:08 +0200285// C.LWSP RD, OFFSET
286static inline void asm_rv32_opcode_clwsp(asm_rv32_t *state, mp_uint_t rd, mp_uint_t offset) {
287 // CI: 010 . ..... ..... 10
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200288 asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CI(0x02, 0x02, rd, ((offset & 0xC0) >> 6) | (offset & 0x3C)));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200289}
290
291// C.MV RD, RS
292static inline void asm_rv32_opcode_cmv(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs) {
293 // CR: 1000 ..... ..... 10
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200294 asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CR(0x02, 0x08, rd, rs));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200295}
296
297// C.SWSP RS, OFFSET
298static inline void asm_rv32_opcode_cswsp(asm_rv32_t *state, mp_uint_t rs, mp_uint_t offset) {
299 // CSS: 010 ...... ..... 10
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200300 asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CSS(0x02, 0x06, rs, ((offset & 0xC0) >> 6) | (offset & 0x3C)));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200301}
302
303// JALR RD, RS, offset
304static inline void asm_rv32_opcode_jalr(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) {
305 // I: ............ ..... 000 ..... 1100111
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200306 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x67, 0x00, rd, rs, offset));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200307}
308
309// LBU RD, OFFSET(RS)
310static inline void asm_rv32_opcode_lbu(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) {
311 // I: ............ ..... 100 ..... 0000011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200312 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x03, 0x04, rd, rs, offset));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200313}
314
315// LHU RD, OFFSET(RS)
316static inline void asm_rv32_opcode_lhu(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) {
317 // I: ............ ..... 101 ..... 0000011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200318 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x03, 0x05, rd, rs, offset));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200319}
320
321// LUI RD, immediate
322static inline void asm_rv32_opcode_lui(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate) {
323 // U: .................... ..... 0110111
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200324 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_U(0x37, rd, immediate));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200325}
326
327// LW RD, OFFSET(RS)
328static inline void asm_rv32_opcode_lw(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) {
329 // I: ............ ..... 010 ..... 0000011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200330 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x03, 0x02, rd, rs, offset));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200331}
332
333// MUL RD, RS1, RS2
Alessandro Gatti326e1142024-07-31 16:56:42 +0200334static inline void asm_rv32_opcode_mul(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) {
Alessandro Gatti8338f662024-06-08 11:00:08 +0200335 // R: 0000001 ..... ..... 000 ..... 0110011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200336 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x00, 0x01, rd, rs1, rs2));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200337}
338
339// OR RD, RS1, RS2
340static inline void asm_rv32_opcode_or(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) {
341 // R: 0000000 ..... ..... 110 ..... 0110011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200342 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x06, 0x00, rd, rs1, rs2));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200343}
344
345// SLL RD, RS1, RS2
346static inline void asm_rv32_opcode_sll(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) {
347 // R: 0000000 ..... ..... 001 ..... 0110011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200348 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x01, 0x00, rd, rs1, rs2));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200349}
350
351// SLLI RD, RS, IMMEDIATE
352static inline void asm_rv32_opcode_slli(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_uint_t immediate) {
353 // I: 0000000..... ..... 001 ..... 0010011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200354 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x13, 0x01, rd, rs, immediate & 0x1F));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200355}
356
357// SRL RD, RS1, RS2
358static inline void asm_rv32_opcode_srl(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) {
359 // R: 0000000 ..... ..... 101 ..... 0110011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200360 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x05, 0x00, rd, rs1, rs2));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200361}
362
363// SLT RD, RS1, RS2
364static inline void asm_rv32_opcode_slt(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) {
365 // R: 0000000 ..... ..... 010 ..... 0110011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200366 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x02, 0x00, rd, rs1, rs2));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200367}
368
369// SLTU RD, RS1, RS2
370static inline void asm_rv32_opcode_sltu(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) {
371 // R: 0000000 ..... ..... 011 ..... 0110011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200372 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x03, 0x00, rd, rs1, rs2));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200373}
374
375// SRA RD, RS1, RS2
376static inline void asm_rv32_opcode_sra(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) {
377 // R: 0100000 ..... ..... 101 ..... 0110011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200378 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x05, 0x20, rd, rs1, rs2));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200379}
380
381// SUB RD, RS1, RS2
382static inline void asm_rv32_opcode_sub(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) {
383 // R: 0100000 ..... ..... 000 ..... 0110011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200384 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x00, 0x20, rd, rs1, rs2));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200385}
386
387// SB RS2, OFFSET(RS1)
388static inline void asm_rv32_opcode_sb(asm_rv32_t *state, mp_uint_t rs2, mp_uint_t rs1, mp_int_t offset) {
389 // S: ....... ..... ..... 000 ..... 0100011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200390 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_S(0x23, 0x00, rs1, rs2, offset));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200391}
392
393// SH RS2, OFFSET(RS1)
394static inline void asm_rv32_opcode_sh(asm_rv32_t *state, mp_uint_t rs2, mp_uint_t rs1, mp_int_t offset) {
395 // S: ....... ..... ..... 001 ..... 0100011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200396 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_S(0x23, 0x01, rs1, rs2, offset));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200397}
398
399// SW RS2, OFFSET(RS1)
400static inline void asm_rv32_opcode_sw(asm_rv32_t *state, mp_uint_t rs2, mp_uint_t rs1, mp_int_t offset) {
401 // S: ....... ..... ..... 010 ..... 0100011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200402 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_S(0x23, 0x02, rs1, rs2, offset));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200403}
404
405// XOR RD, RS1, RS2
406static inline void asm_rv32_opcode_xor(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) {
407 // R: 0000000 ..... ..... 100 ..... 0110011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200408 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x04, 0x00, rd, rs1, rs2));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200409}
410
411// XORI RD, RS, IMMEDIATE
412static inline void asm_rv32_opcode_xori(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t immediate) {
413 // I: ............ ..... 100 ..... 0010011
Alessandro Gattibb6a4662024-07-01 22:44:02 +0200414 asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x13, 0x04, rd, rs, immediate));
Alessandro Gatti8338f662024-06-08 11:00:08 +0200415}
416
417#define ASM_WORD_SIZE (4)
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200418#define ASM_HALFWORD_SIZE (2)
Alessandro Gatti8338f662024-06-08 11:00:08 +0200419
420#define REG_RET ASM_RV32_REG_A0
421#define REG_ARG_1 ASM_RV32_REG_A0
422#define REG_ARG_2 ASM_RV32_REG_A1
423#define REG_ARG_3 ASM_RV32_REG_A2
424#define REG_ARG_4 ASM_RV32_REG_A3
425#define REG_TEMP0 ASM_RV32_REG_T1
426#define REG_TEMP1 ASM_RV32_REG_T2
427#define REG_TEMP2 ASM_RV32_REG_T3
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200428#define REG_FUN_TABLE ASM_RV32_REG_S1
Alessandro Gatti8338f662024-06-08 11:00:08 +0200429#define REG_LOCAL_1 ASM_RV32_REG_S3
430#define REG_LOCAL_2 ASM_RV32_REG_S4
431#define REG_LOCAL_3 ASM_RV32_REG_S5
432
433void asm_rv32_meta_comparison_eq(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd);
434void asm_rv32_meta_comparison_ne(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd);
435void asm_rv32_meta_comparison_lt(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd, bool unsigned_comparison);
436void asm_rv32_meta_comparison_le(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd, bool unsigned_comparison);
437
438#ifdef GENERIC_ASM_API
439
440void asm_rv32_emit_call_ind(asm_rv32_t *state, mp_uint_t index);
441void asm_rv32_emit_jump(asm_rv32_t *state, mp_uint_t label);
442void asm_rv32_emit_jump_if_reg_eq(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t label);
443void asm_rv32_emit_jump_if_reg_nonzero(asm_rv32_t *state, mp_uint_t rs, mp_uint_t label);
444void asm_rv32_emit_load16_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset);
445void asm_rv32_emit_load_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset);
446void asm_rv32_emit_mov_local_reg(asm_rv32_t *state, mp_uint_t local, mp_uint_t rs);
447void asm_rv32_emit_mov_reg_local(asm_rv32_t *state, mp_uint_t rd, mp_uint_t local);
448void asm_rv32_emit_mov_reg_local_addr(asm_rv32_t *state, mp_uint_t rd, mp_uint_t local);
449void asm_rv32_emit_mov_reg_pcrel(asm_rv32_t *state, mp_uint_t rd, mp_uint_t label);
450void asm_rv32_emit_optimised_load_immediate(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate);
451void asm_rv32_emit_optimised_xor(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs);
452void asm_rv32_emit_store_reg_reg_offset(asm_rv32_t *state, mp_uint_t source, mp_uint_t base, mp_int_t offset);
453
454#define ASM_T asm_rv32_t
455#define ASM_ENTRY(state, labels) asm_rv32_entry(state, labels)
456#define ASM_EXIT(state) asm_rv32_exit(state)
457#define ASM_END_PASS(state) asm_rv32_end_pass(state)
458
459#define ASM_ADD_REG_REG(state, rd, rs) asm_rv32_opcode_cadd(state, rd, rs)
460#define ASM_AND_REG_REG(state, rd, rs) asm_rv32_opcode_and(state, rd, rs, rd)
461#define ASM_ASR_REG_REG(state, rd, rs) asm_rv32_opcode_sra(state, rd, rd, rs)
462#define ASM_CALL_IND(state, index) asm_rv32_emit_call_ind(state, index)
463#define ASM_JUMP(state, label) asm_rv32_emit_jump(state, label)
464#define ASM_JUMP_IF_REG_EQ(state, rs1, rs2, label) asm_rv32_emit_jump_if_reg_eq(state, rs1, rs2, label)
465#define ASM_JUMP_IF_REG_NONZERO(state, rs, label, bool_test) asm_rv32_emit_jump_if_reg_nonzero(state, rs, label)
466#define ASM_JUMP_IF_REG_ZERO(state, rs, label, bool_test) asm_rv32_emit_jump_if_reg_eq(state, rs, ASM_RV32_REG_ZERO, label)
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200467#define ASM_JUMP_REG(state, rs) asm_rv32_opcode_cjr(state, rs)
Alessandro Gatti8338f662024-06-08 11:00:08 +0200468#define ASM_LOAD16_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_load16_reg_reg_offset(state, rd, rs, offset)
469#define ASM_LOAD16_REG_REG(state, rd, rs) asm_rv32_opcode_lhu(state, rd, rs, 0)
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200470#define ASM_LOAD32_REG_REG(state, rd, rs) ASM_LOAD_REG_REG_OFFSET(state, rd, rs, 0)
Alessandro Gatti8338f662024-06-08 11:00:08 +0200471#define ASM_LOAD8_REG_REG(state, rd, rs) asm_rv32_opcode_lbu(state, rd, rs, 0)
472#define ASM_LOAD_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_load_reg_reg_offset(state, rd, rs, offset)
473#define ASM_LOAD_REG_REG(state, rd, rs) ASM_LOAD32_REG_REG(state, rd, rs)
474#define ASM_LSL_REG_REG(state, rd, rs) asm_rv32_opcode_sll(state, rd, rd, rs)
475#define ASM_LSR_REG_REG(state, rd, rs) asm_rv32_opcode_srl(state, rd, rd, rs)
476#define ASM_MOV_LOCAL_REG(state, local, rs) asm_rv32_emit_mov_local_reg(state, local, rs)
477#define ASM_MOV_REG_IMM(state, rd, imm) asm_rv32_emit_optimised_load_immediate(state, rd, imm)
478#define ASM_MOV_REG_LOCAL_ADDR(state, rd, local) asm_rv32_emit_mov_reg_local_addr(state, rd, local)
479#define ASM_MOV_REG_LOCAL(state, rd, local) asm_rv32_emit_mov_reg_local(state, rd, local)
480#define ASM_MOV_REG_PCREL(state, rd, label) asm_rv32_emit_mov_reg_pcrel(state, rd, label)
481#define ASM_MOV_REG_REG(state, rd, rs) asm_rv32_opcode_cmv(state, rd, rs)
Alessandro Gatti326e1142024-07-31 16:56:42 +0200482#define ASM_MUL_REG_REG(state, rd, rs) asm_rv32_opcode_mul(state, rd, rd, rs)
Alessandro Gatti8338f662024-06-08 11:00:08 +0200483#define ASM_NEG_REG(state, rd) asm_rv32_opcode_sub(state, rd, ASM_RV32_REG_ZERO, rd)
484#define ASM_NOT_REG(state, rd) asm_rv32_opcode_xori(state, rd, rd, -1)
485#define ASM_OR_REG_REG(state, rd, rs) asm_rv32_opcode_or(state, rd, rd, rs)
486#define ASM_STORE16_REG_REG(state, rs1, rs2) asm_rv32_opcode_sh(state, rs1, rs2, 0)
Alessandro Gatti0600e4f2024-06-25 15:45:13 +0200487#define ASM_STORE32_REG_REG(state, rs1, rs2) ASM_STORE_REG_REG_OFFSET(state, rs1, rs2, 0)
Alessandro Gatti8338f662024-06-08 11:00:08 +0200488#define ASM_STORE8_REG_REG(state, rs1, rs2) asm_rv32_opcode_sb(state, rs1, rs2, 0)
489#define ASM_STORE_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_store_reg_reg_offset(state, rd, rs, offset)
490#define ASM_STORE_REG_REG(state, rs1, rs2) ASM_STORE32_REG_REG(state, rs1, rs2)
491#define ASM_SUB_REG_REG(state, rd, rs) asm_rv32_opcode_sub(state, rd, rd, rs)
492#define ASM_XOR_REG_REG(state, rd, rs) asm_rv32_emit_optimised_xor(state, rd, rs)
493
494#endif
495
496#endif // MICROPY_INCLUDED_PY_ASMRV32_H