-
Notifications
You must be signed in to change notification settings - Fork 3
/
new_instructions_support.h
147 lines (140 loc) · 5.06 KB
/
new_instructions_support.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#ifndef __NEW_INSTRUCTION_SUPPORT_H__
#define __NEW_INSTRUCTION_SUPPORT_H__
#include <stdint.h>
typedef uint32_t uint_xlen_t;
#define XLEN 32
//when missing in toolchain...
// macro to build the function to access the assembly instructions
// unary
#define FUN1(NAME, ASNAME) \
static inline uint32_t NAME(uint32_t rs1) { \
uint32_t r; \
asm (#ASNAME " reg_%0, reg_%1\n" \
: "=r" (r) \
: "r" (rs1)); \
return r; \
}
// binary
#define FUN2(NAME, ASNAME) \
static inline uint_xlen_t NAME(uint_xlen_t rs1, uint_xlen_t rs2) { \
uint32_t r; \
asm (#ASNAME " reg_%0, reg_%1, reg_%2\n" \
: "=r" (r) \
: "r" (rs1), "r" (rs2)); \
return r; \
}
// binary (destructive, UNUSED [K removed it in 0.9.2])
#define FUN2F(NAME, ASNAME) \
static inline uint32_t NAME(uint32_t rs1, uint32_t rs2) { \
uint32_t r = rs1; \
asm (#ASNAME " reg_%0, reg_%1\n" \
: "+&r" (r) \
: "r" (rs2)); \
return r; \
}
// ternary (constructive, e.g. cmov from B)
#define FUN3(NAME, ASNAME) \
static inline uint_xlen_t NAME(uint_xlen_t rs1, uint_xlen_t rs2, uint_xlen_t rs3) { \
uint32_t r; \
asm (#ASNAME " reg_%0, reg_%1, reg_%2, reg_%3\n" \
: "=r" (r) \
: "r" (rs1), "r" (rs2), "r" (rs3)); \
return r; \
}
// ternary (destructive, e.g. pbsad from P)
#define FUN3R(NAME, ASNAME) \
static inline uint_xlen_t NAME(uint_xlen_t rs1, uint_xlen_t rs2, uint_xlen_t rs3) { \
uint32_t r = rs3; \
asm (#ASNAME " reg_%0, reg_%1, reg_%2\n" \
: "+&r" (r) \
: "r" (rs1), "r" (rs2)); \
return r; \
}
// ternary (destructive using an immediate, e.g. insb from P)
#define FUN3RI(NAME, ASNAME, IMM) \
static inline uint_xlen_t NAME##IMM(uint_xlen_t rs1, uint_xlen_t rs3) { \
uint32_t r = rs3; \
asm (#ASNAME " reg_%0, reg_%1, " #IMM "\n" \
: "+&r" (r) \
: "r" (rs1)); \
return r; \
}
// binary wide (64-bits output in R2n/R2n+1, e.g. smul8 from P)
#define FUN2W(NAME, ASNAME) \
static inline uint64_t NAME(uint_xlen_t rs1, uint_xlen_t rs2) { \
register uint32_t r0 asm ("t5"), r1 asm ("t6"); \
asm (#ASNAME " reg_%0, reg_%2, reg_%3\n" \
: "=r" (r0), "=r" (r1) \
: "r" (rs1), "r" (rs2)); \
return ((uint64_t)r0 | (((uint64_t)r1)<<32)); \
}
// ternary wide (64-bits output in R2n/R2n+1)
#define FUN3Wx(NAME, ASNAME, r0, r1) \
static inline uint64_t NAME(uint_xlen_t rs1, uint_xlen_t rs2, uint_xlen_t rs3) { \
register uint32_t r0 asm (""#r0), r1 asm (""#r1); \
r0 = rs3; \
asm (#ASNAME " reg_%0, reg_%2, reg_%3\n" \
: "+r" (r0), "=r" (r1) \
: "r" (rs1), "r" (rs2)); \
return ((uint64_t)r0 | (((uint64_t)r1)<<32)); \
}
#define FUN3Wt5(NAME, ASNAME) FUN3Wx(NAME, ASNAME, t5, t6)
#define FUN3Wt3(NAME, ASNAME) FUN3Wx(NAME, ASNAME, t3, t4)
#define FUN3Ws10(NAME, ASNAME) FUN3Wx(NAME, ASNAME, s10, s11)
#define FUN3Ws8(NAME, ASNAME) FUN3Wx(NAME, ASNAME, s8, s9)
// macro to build assembly macros to generate the proper
// opcodes as .word macro
// the translation from name to number is done my the
// defines below, so this need to go .c -> .S -> .o
// so that there preprocessor is applied to the
// intermediate .S file
#define ASM1MACRO(N, O) asm(".macro "#N" rd, rs1\n" \
".word ("#O" | (\\rd << 7) | (\\rs1 << 15))\n" \
".endm\n");
#define ASM2MACRO(N, O) asm(".macro "#N" rd, rs1, rs2\n" \
".word ("#O" | (\\rd << 7) | (\\rs1 << 15) | (\\rs2 << 20))\n" \
".endm\n");
#define ASM2FMACRO(N, O) asm(".macro "#N" rt, rs2\n" \
".word ("#O" | (\\rt << 15) | (\\rs2 << 20))\n" \
".endm\n");
#define ASM3MACRO(N, O) asm(".macro "#N" rd, rs1, rs2, rs3\n" \
".word ("#O" | (\\rd << 7) | (\\rs1 << 15) | (\\rs2 << 20) | (\\rs3 << 27) )\n" \
".endm\n");
#define ASM3RMACRO(N, O) ASM2MACRO(N, O)
#define ASM3RIMACRO(N, O) asm(".macro "#N" rd, rs1, imm\n" \
".word ("#O" | (\\rd << 7) | (\\rs1 << 15) | (\\imm << 20))\n" \
".endm\n");
// register name -> number mapping
asm("#define reg_zero 0\n");
asm("#define reg_ra 1\n");
asm("#define reg_sp 2\n");
asm("#define reg_gp 3\n");
asm("#define reg_tp 4\n");
asm("#define reg_t0 5\n");
asm("#define reg_t1 6\n");
asm("#define reg_t2 7\n");
asm("#define reg_s0 8\n");
asm("#define reg_s1 9\n");
asm("#define reg_a0 10\n");
asm("#define reg_a1 11\n");
asm("#define reg_a2 12\n");
asm("#define reg_a3 13\n");
asm("#define reg_a4 14\n");
asm("#define reg_a5 15\n");
asm("#define reg_a6 16\n");
asm("#define reg_a7 17\n");
asm("#define reg_s2 18\n");
asm("#define reg_s3 19\n");
asm("#define reg_s4 20\n");
asm("#define reg_s5 21\n");
asm("#define reg_s6 22\n");
asm("#define reg_s7 23\n");
asm("#define reg_s8 24\n");
asm("#define reg_s9 25\n");
asm("#define reg_s10 26\n");
asm("#define reg_s11 27\n");
asm("#define reg_t3 28\n");
asm("#define reg_t4 29\n");
asm("#define reg_t5 30\n");
asm("#define reg_t6 31\n");
#endif // __NEW_INSTRUCTION_SUPPORT_H__