1*ce95e1b3SDavid du Colombier #include <u.h>
2*ce95e1b3SDavid du Colombier #include <libc.h>
3*ce95e1b3SDavid du Colombier #include <bio.h>
4*ce95e1b3SDavid du Colombier #include <mach.h>
5*ce95e1b3SDavid du Colombier #include "../cmd/ic/i.out.h"
6*ce95e1b3SDavid du Colombier
7*ce95e1b3SDavid du Colombier static char *riscvexcep(Map*, Rgetter);
8*ce95e1b3SDavid du Colombier
9*ce95e1b3SDavid du Colombier /*
10*ce95e1b3SDavid du Colombier * RISCV-specific debugger interface
11*ce95e1b3SDavid du Colombier */
12*ce95e1b3SDavid du Colombier
13*ce95e1b3SDavid du Colombier typedef struct Instr Instr;
14*ce95e1b3SDavid du Colombier struct Instr
15*ce95e1b3SDavid du Colombier {
16*ce95e1b3SDavid du Colombier Map *map;
17*ce95e1b3SDavid du Colombier ulong w;
18*ce95e1b3SDavid du Colombier uvlong addr;
19*ce95e1b3SDavid du Colombier char *fmt;
20*ce95e1b3SDavid du Colombier int n;
21*ce95e1b3SDavid du Colombier int op;
22*ce95e1b3SDavid du Colombier int aop;
23*ce95e1b3SDavid du Colombier int func3;
24*ce95e1b3SDavid du Colombier int func7;
25*ce95e1b3SDavid du Colombier char rs1, rs2, rs3, rd;
26*ce95e1b3SDavid du Colombier char rv64;
27*ce95e1b3SDavid du Colombier long imm;
28*ce95e1b3SDavid du Colombier
29*ce95e1b3SDavid du Colombier char* curr; /* fill point in buffer */
30*ce95e1b3SDavid du Colombier char* end; /* end of buffer */
31*ce95e1b3SDavid du Colombier };
32*ce95e1b3SDavid du Colombier
33*ce95e1b3SDavid du Colombier typedef struct Optab Optab;
34*ce95e1b3SDavid du Colombier struct Optab {
35*ce95e1b3SDavid du Colombier int func7;
36*ce95e1b3SDavid du Colombier int op[8];
37*ce95e1b3SDavid du Colombier };
38*ce95e1b3SDavid du Colombier
39*ce95e1b3SDavid du Colombier typedef struct Opclass Opclass;
40*ce95e1b3SDavid du Colombier struct Opclass {
41*ce95e1b3SDavid du Colombier char *fmt;
42*ce95e1b3SDavid du Colombier Optab tab[4];
43*ce95e1b3SDavid du Colombier };
44*ce95e1b3SDavid du Colombier
45*ce95e1b3SDavid du Colombier /* Major opcodes */
46*ce95e1b3SDavid du Colombier enum {
47*ce95e1b3SDavid du Colombier OLOAD, OLOAD_FP, Ocustom_0, OMISC_MEM, OOP_IMM, OAUIPC, OOP_IMM_32, O48b,
48*ce95e1b3SDavid du Colombier OSTORE, OSTORE_FP, Ocustom_1, OAMO, OOP, OLUI, OOP_32, O64b,
49*ce95e1b3SDavid du Colombier OMADD, OMSUB, ONMSUB, ONMADD, OOP_FP, Ores_0, Ocustom_2, O48b_2,
50*ce95e1b3SDavid du Colombier OBRANCH, OJALR, Ores_1, OJAL, OSYSTEM, Ores_2, Ocustom_3, O80b
51*ce95e1b3SDavid du Colombier };
52*ce95e1b3SDavid du Colombier
53*ce95e1b3SDavid du Colombier /* copy anames from compiler */
54*ce95e1b3SDavid du Colombier static
55*ce95e1b3SDavid du Colombier #include "../cmd/ic/enam.c"
56*ce95e1b3SDavid du Colombier
57*ce95e1b3SDavid du Colombier static Opclass opOLOAD = {
58*ce95e1b3SDavid du Colombier "a,d",
59*ce95e1b3SDavid du Colombier 0, AMOVB, AMOVH, AMOVW, AMOV, AMOVBU, AMOVHU, AMOVWU, 0,
60*ce95e1b3SDavid du Colombier };
61*ce95e1b3SDavid du Colombier static Opclass opOLOAD_FP = {
62*ce95e1b3SDavid du Colombier "a,fd",
63*ce95e1b3SDavid du Colombier 0, 0, 0, AMOVF, AMOVD, 0, 0, 0, 0,
64*ce95e1b3SDavid du Colombier };
65*ce95e1b3SDavid du Colombier static Opclass opOMISC_MEM = {
66*ce95e1b3SDavid du Colombier "",
67*ce95e1b3SDavid du Colombier 0, AFENCE, AFENCE_I,0, 0, 0, 0, 0, 0,
68*ce95e1b3SDavid du Colombier };
69*ce95e1b3SDavid du Colombier static Opclass opOOP_IMM = {
70*ce95e1b3SDavid du Colombier "$i,s,d",
71*ce95e1b3SDavid du Colombier 0x20, 0, 0, 0, 0, 0, ASRA, 0, 0,
72*ce95e1b3SDavid du Colombier 0, AADD, ASLL, ASLT, ASLTU, AXOR, ASRL, AOR, AAND,
73*ce95e1b3SDavid du Colombier };
74*ce95e1b3SDavid du Colombier static Opclass opOAUIPC = {
75*ce95e1b3SDavid du Colombier "$i(PC),d",
76*ce95e1b3SDavid du Colombier 0, ALUI, ALUI, ALUI, ALUI, ALUI, ALUI, ALUI, ALUI,
77*ce95e1b3SDavid du Colombier };
78*ce95e1b3SDavid du Colombier static Opclass opOOP_IMM_32 = {
79*ce95e1b3SDavid du Colombier "$i,s,d",
80*ce95e1b3SDavid du Colombier 0x20, 0, 0, 0, 0, 0, ASRAW, 0, 0,
81*ce95e1b3SDavid du Colombier 0, AADDW, ASLLW, 0, 0, 0, ASRLW, 0, 0,
82*ce95e1b3SDavid du Colombier };
83*ce95e1b3SDavid du Colombier static Opclass opOSTORE = {
84*ce95e1b3SDavid du Colombier "2,a",
85*ce95e1b3SDavid du Colombier 0, AMOVB, AMOVH, AMOVW, AMOV, 0, 0, 0, 0,
86*ce95e1b3SDavid du Colombier };
87*ce95e1b3SDavid du Colombier static Opclass opOSTORE_FP = {
88*ce95e1b3SDavid du Colombier "f2,a",
89*ce95e1b3SDavid du Colombier 0, 0, 0, AMOVF, AMOVD, 0, 0, 0, 0,
90*ce95e1b3SDavid du Colombier };
91*ce95e1b3SDavid du Colombier static Opclass opOAMO = {
92*ce95e1b3SDavid du Colombier "7,2,s,d",
93*ce95e1b3SDavid du Colombier 0x04, 0, 0, ASWAP_W,ASWAP_D,0, 0, 0, 0,
94*ce95e1b3SDavid du Colombier 0x08, 0, 0, ALR_W, ALR_D, 0, 0, 0, 0,
95*ce95e1b3SDavid du Colombier 0x0C, 0, 0, ASC_W, ASC_D, 0, 0, 0, 0,
96*ce95e1b3SDavid du Colombier 0, 0, 0, AAMO_W, AAMO_D, 0, 0, 0, 0,
97*ce95e1b3SDavid du Colombier };
98*ce95e1b3SDavid du Colombier static Opclass opOOP = {
99*ce95e1b3SDavid du Colombier "2,s,d",
100*ce95e1b3SDavid du Colombier 0x01, AMUL, AMULH, AMULHSU,AMULHU, ADIV, ADIVU, AREM, AREMU,
101*ce95e1b3SDavid du Colombier 0x20, ASUB, 0, 0, 0, 0, ASRA, 0, 0,
102*ce95e1b3SDavid du Colombier 0, AADD, ASLL, ASLT, ASLTU, AXOR, ASRL, AOR, AAND,
103*ce95e1b3SDavid du Colombier };
104*ce95e1b3SDavid du Colombier static Opclass opOLUI = {
105*ce95e1b3SDavid du Colombier "$i,d",
106*ce95e1b3SDavid du Colombier 0, ALUI, ALUI, ALUI, ALUI, ALUI, ALUI, ALUI, ALUI,
107*ce95e1b3SDavid du Colombier };
108*ce95e1b3SDavid du Colombier static Opclass opOOP_32 = {
109*ce95e1b3SDavid du Colombier "2,s,d",
110*ce95e1b3SDavid du Colombier 0x01, AMULW, 0, 0, 0, ADIVW, ADIVUW, AREMW, AREMUW,
111*ce95e1b3SDavid du Colombier 0x20, ASUBW, 0, 0, 0, 0, ASRAW, 0, 0,
112*ce95e1b3SDavid du Colombier 0, AADDW, ASLLW, 0, 0, 0, ASRLW, 0, 0,
113*ce95e1b3SDavid du Colombier };
114*ce95e1b3SDavid du Colombier static Opclass opOBRANCH = {
115*ce95e1b3SDavid du Colombier "2,s,p",
116*ce95e1b3SDavid du Colombier 0, ABEQ, ABNE, 0, 0, ABLT, ABGE, ABLTU, ABGEU,
117*ce95e1b3SDavid du Colombier };
118*ce95e1b3SDavid du Colombier static Opclass opOJALR = {
119*ce95e1b3SDavid du Colombier "d,a",
120*ce95e1b3SDavid du Colombier 0, AJALR, AJALR, AJALR, AJALR, AJALR, AJALR, AJALR, AJALR,
121*ce95e1b3SDavid du Colombier };
122*ce95e1b3SDavid du Colombier static Opclass opOJAL = {
123*ce95e1b3SDavid du Colombier "d,p",
124*ce95e1b3SDavid du Colombier 0, AJAL, AJAL, AJAL, AJAL, AJAL, AJAL, AJAL, AJAL,
125*ce95e1b3SDavid du Colombier };
126*ce95e1b3SDavid du Colombier static Opclass opOSYSTEM = {
127*ce95e1b3SDavid du Colombier "",
128*ce95e1b3SDavid du Colombier 0, ASYS, ACSRRW, ACSRRS, ACSRRC, 0, ACSRRWI,ACSRRSI,ACSRRCI,
129*ce95e1b3SDavid du Colombier };
130*ce95e1b3SDavid du Colombier static char fmtcsr[] = "c,s,d";
131*ce95e1b3SDavid du Colombier static char fmtcsri[] = "c,js,d";
132*ce95e1b3SDavid du Colombier static char *fmtOSYSTEM[8] = {
133*ce95e1b3SDavid du Colombier "$i", fmtcsr, fmtcsr, fmtcsr, "", fmtcsri, fmtcsri, fmtcsri,
134*ce95e1b3SDavid du Colombier };
135*ce95e1b3SDavid du Colombier static Opclass opOOP_FP = {
136*ce95e1b3SDavid du Colombier "fs,fd",
137*ce95e1b3SDavid du Colombier 0x0, AADDF, ASUBF, AMULF, ADIVF, AMOVF, 0, 0, 0,
138*ce95e1b3SDavid du Colombier 0x1, AMOVDF, 0, 0, 0, 0, 0, 0, 0,
139*ce95e1b3SDavid du Colombier 0x2, ACMPLEF,ACMPLTF,ACMPEQF,0, 0, 0, 0, 0,
140*ce95e1b3SDavid du Colombier 0x3, AMOVFW, 0, AMOVFV, 0, AMOVWF, AMOVUF, AMOVVF, AMOVUVF,
141*ce95e1b3SDavid du Colombier };
142*ce95e1b3SDavid du Colombier static Opclass opOOP_DP = {
143*ce95e1b3SDavid du Colombier "f2,fs,fd",
144*ce95e1b3SDavid du Colombier 0x0, AADDD, ASUBD, AMULD, ADIVD, AMOVD, 0, 0, 0,
145*ce95e1b3SDavid du Colombier 0x1, AMOVFD, 0, 0, 0, 0, 0, 0, 0,
146*ce95e1b3SDavid du Colombier 0x2, ACMPLED,ACMPLTD,ACMPEQD,0, 0, 0, 0, 0,
147*ce95e1b3SDavid du Colombier 0x3, AMOVDW, 0, AMOVDV, 0, AMOVWD, AMOVUD, AMOVVD, AMOVUVD,
148*ce95e1b3SDavid du Colombier };
149*ce95e1b3SDavid du Colombier
150*ce95e1b3SDavid du Colombier typedef struct Compclass Compclass;
151*ce95e1b3SDavid du Colombier struct Compclass {
152*ce95e1b3SDavid du Colombier char *fmt;
153*ce95e1b3SDavid du Colombier uchar immbits[18];
154*ce95e1b3SDavid du Colombier };
155*ce95e1b3SDavid du Colombier
156*ce95e1b3SDavid du Colombier static Compclass rv32compressed[0x2E] = {
157*ce95e1b3SDavid du Colombier /* 00-07 ([1:0] = 0) ([15:13] = 0-7) */
158*ce95e1b3SDavid du Colombier {"ADDI4SPN $i,d", 22, 6, 5, 11, 12, 7, 8, 9, 10}, /* 12:5 → 5:4|9:6|2|3 */
159*ce95e1b3SDavid du Colombier {"FLD a,fd", 24, 10, 11, 12, 5, 6}, /* 12:10|6:5 → 5:3|7:6 */
160*ce95e1b3SDavid du Colombier {"LW a,d", 25, 6, 10, 11, 12, 5}, /* 12:10|6:5 → 5:2|6 */
161*ce95e1b3SDavid du Colombier {"FLW a,fd", 25, 6, 10, 11, 12, 5}, /* 12:10|6:5 → 5:2|6 rv32 */
162*ce95e1b3SDavid du Colombier {"? ", 0},
163*ce95e1b3SDavid du Colombier {"FSD f2,a", 24, 10, 11, 12, 5, 6}, /* 12:10|6:5 → 5:3|7:6 */
164*ce95e1b3SDavid du Colombier {"SW 2,a", 25, 6, 10, 11, 12, 5}, /* 12:10|6:5 → 5:2|6 */
165*ce95e1b3SDavid du Colombier {"FSW f2,a", 25, 6, 10, 11, 12, 5}, /* 12:10|6:5 → 5:2|6 rv32 */
166*ce95e1b3SDavid du Colombier
167*ce95e1b3SDavid du Colombier /* 08-0F ([1:0] = 1) ([15:13] = 0-7 not 4) */
168*ce95e1b3SDavid du Colombier {"ADDI $i,d", ~26, 2, 3, 4, 5, 6, 12}, /* 12|6:2 → * 5:0 */
169*ce95e1b3SDavid du Colombier {"JAL p", ~20, 3, 4, 5, 11, 2, 7, 6, 9, 10, 8, 12}, /* 12:2 → * 11|4|9:8|10|6|7|3:1|5 rv32 D*/
170*ce95e1b3SDavid du Colombier {"LI $i,d", ~26, 2, 3, 4, 5, 6, 12}, /* 12|6:2 → * 5:0 */
171*ce95e1b3SDavid du Colombier {"LUI $i,d", ~14, 2, 3, 4, 5, 6, 12}, /* 12|6:2 → * 17:12 */
172*ce95e1b3SDavid du Colombier {"? ", 0},
173*ce95e1b3SDavid du Colombier {"J p", ~20, 3, 4, 5, 11, 2, 7, 6, 9, 10, 8, 12}, /* 12:2 → * 11|4|9:8|10|6|7|3:1|5 */
174*ce95e1b3SDavid du Colombier {"BEQZ s,p", ~23, 3, 4, 10, 11, 2, 5, 6, 12}, /* 12:10|6:2 → * 8|4|3|7:6|2:1|5 */
175*ce95e1b3SDavid du Colombier {"BNEZ s,p", ~23, 3, 4, 10, 11, 2, 5, 6, 12}, /* 12:10|6:2 → * 8|4|3|7:6|2:1|5 */
176*ce95e1b3SDavid du Colombier
177*ce95e1b3SDavid du Colombier /* 10-17 ([1:0] = 2) ([15:13] = 0-7 not 4) */
178*ce95e1b3SDavid du Colombier {"SLLI $i,d", 26, 2, 3, 4, 5, 6, 12}, /* 12|6:2 → 5:0 */
179*ce95e1b3SDavid du Colombier {"FLDSP i,fd", 23, 5, 6, 12, 2, 3, 4}, /* 12|6:2 → 5:3|8:6 */
180*ce95e1b3SDavid du Colombier {"LWSP i,d", 24, 4, 5, 6, 12, 2, 3}, /* 12|6:2 → 5:2|7:6 */
181*ce95e1b3SDavid du Colombier {"FLWSP i,fd", 24, 4, 5, 6, 12, 2, 3}, /* 12|6:2 → 5:2|7:6 rv32 */
182*ce95e1b3SDavid du Colombier {"? ", 0},
183*ce95e1b3SDavid du Colombier {"FSDSP f2,$i", 23, 10, 11, 12, 7, 8, 9}, /* 12:7 → 5:3|8:6 */
184*ce95e1b3SDavid du Colombier {"SWSP 2,$i", 24, 9, 10, 11, 12, 7, 8}, /* 12:7 → 5:2|7:6 */
185*ce95e1b3SDavid du Colombier {"FSWSP f2,$i", 24, 9, 10, 11, 12, 7, 8}, /* 12:7 → 5:2|7:6 rv32 */
186*ce95e1b3SDavid du Colombier
187*ce95e1b3SDavid du Colombier /* 18-1A ([1:0] = 1) ([15:13] = 4) ([11:10] = 0-2) */
188*ce95e1b3SDavid du Colombier {"SRLI $i,d", 26, 2, 3, 4, 5, 6, 12}, /* 12|6:2 → 5:0 */
189*ce95e1b3SDavid du Colombier {"SRAI $i,d", 26, 2, 3, 4, 5, 6, 12}, /* 12|6:2 → 5:0 */
190*ce95e1b3SDavid du Colombier {"ANDI $i,d", ~26, 2, 3, 4, 5, 6, 12}, /* 12|6:2 → * 5:0 */
191*ce95e1b3SDavid du Colombier
192*ce95e1b3SDavid du Colombier /* 1B-22 ([1:0] = 1) ([15:13] = 4) ([11:10] = 3) ([12] = 0-1) ([6:5] = 0-3) */
193*ce95e1b3SDavid du Colombier {"SUB 2,d", 0},
194*ce95e1b3SDavid du Colombier {"XOR 2,d", 0},
195*ce95e1b3SDavid du Colombier {"OR 2,d", 0},
196*ce95e1b3SDavid du Colombier {"AND 2,d", 0},
197*ce95e1b3SDavid du Colombier {"SUBW 2,d", 0}, /* rv64 */
198*ce95e1b3SDavid du Colombier {"ADDW 2,d", 0}, /* rv64 */
199*ce95e1b3SDavid du Colombier {"? ", 0},
200*ce95e1b3SDavid du Colombier {"? ", 0},
201*ce95e1b3SDavid du Colombier
202*ce95e1b3SDavid du Colombier /* 23-26 ([1:0] = 2) ([15:13] = 4) ([12] = 0-1) ((rs2 != 0) = 0-1) */
203*ce95e1b3SDavid du Colombier {"JR s", 0},
204*ce95e1b3SDavid du Colombier {"MV 2,d", 0},
205*ce95e1b3SDavid du Colombier {"JALR s", 0},
206*ce95e1b3SDavid du Colombier {"ADD 2,d", 0},
207*ce95e1b3SDavid du Colombier
208*ce95e1b3SDavid du Colombier /* 27-27 ([1:0] = 1) ([15:13] = 3) ( rd = 2) */
209*ce95e1b3SDavid du Colombier {"ADDI16SP $i", ~22, 6, 2, 5, 3, 4, 12}, /* 12|6:2 → * 9|4|6|8:7|5 */
210*ce95e1b3SDavid du Colombier
211*ce95e1b3SDavid du Colombier /* 28-2C rv64 alternates */
212*ce95e1b3SDavid du Colombier {"LD a,d", 24, 10, 11, 12, 5, 6}, /* 12:10|6:5 → 5:3|7:6 */
213*ce95e1b3SDavid du Colombier {"SD 2,a", 24, 10, 11, 12, 5, 6}, /* 12:10|6:5 → 5:3|7:6 */
214*ce95e1b3SDavid du Colombier {"ADDIW $i,d", ~26, 2, 3, 4, 5, 6, 12}, /* 12|6:2 → * 5:0 */
215*ce95e1b3SDavid du Colombier {"LDSP i,d", 23, 5, 6, 12, 2, 3, }, /* 12|6:2 → 5:3|8:6 */
216*ce95e1b3SDavid du Colombier {"SDSP 2,i", 23, 10, 11, 12, 7, 8, 9}, /* 12:7 → 5:3|8:6 */
217*ce95e1b3SDavid du Colombier
218*ce95e1b3SDavid du Colombier /* 2D-2D C.ADD with (rd = 0) */
219*ce95e1b3SDavid du Colombier {"EBREAK", 0 }
220*ce95e1b3SDavid du Colombier };
221*ce95e1b3SDavid du Colombier
222*ce95e1b3SDavid du Colombier /* map major opcodes to opclass table */
223*ce95e1b3SDavid du Colombier static Opclass *opclass[32] = {
224*ce95e1b3SDavid du Colombier [OLOAD] &opOLOAD,
225*ce95e1b3SDavid du Colombier [OLOAD_FP] &opOLOAD_FP,
226*ce95e1b3SDavid du Colombier [OMISC_MEM] &opOMISC_MEM,
227*ce95e1b3SDavid du Colombier [OOP_IMM] &opOOP_IMM,
228*ce95e1b3SDavid du Colombier [OAUIPC] &opOAUIPC,
229*ce95e1b3SDavid du Colombier [OOP_IMM_32] &opOOP_IMM_32,
230*ce95e1b3SDavid du Colombier [OSTORE] &opOSTORE,
231*ce95e1b3SDavid du Colombier [OSTORE_FP] &opOSTORE_FP,
232*ce95e1b3SDavid du Colombier [OAMO] &opOAMO,
233*ce95e1b3SDavid du Colombier [OOP] &opOOP,
234*ce95e1b3SDavid du Colombier [OLUI] &opOLUI,
235*ce95e1b3SDavid du Colombier [OOP_FP] &opOOP_FP,
236*ce95e1b3SDavid du Colombier [OOP_32] &opOOP_32,
237*ce95e1b3SDavid du Colombier [OBRANCH] &opOBRANCH,
238*ce95e1b3SDavid du Colombier [OJALR] &opOJALR,
239*ce95e1b3SDavid du Colombier [OJAL] &opOJAL,
240*ce95e1b3SDavid du Colombier [OSYSTEM] &opOSYSTEM,
241*ce95e1b3SDavid du Colombier };
242*ce95e1b3SDavid du Colombier
243*ce95e1b3SDavid du Colombier /*
244*ce95e1b3SDavid du Colombier * Print value v as name[+offset]
245*ce95e1b3SDavid du Colombier */
246*ce95e1b3SDavid du Colombier static int
gsymoff(char * buf,int n,ulong v,int space)247*ce95e1b3SDavid du Colombier gsymoff(char *buf, int n, ulong v, int space)
248*ce95e1b3SDavid du Colombier {
249*ce95e1b3SDavid du Colombier Symbol s;
250*ce95e1b3SDavid du Colombier int r;
251*ce95e1b3SDavid du Colombier long delta;
252*ce95e1b3SDavid du Colombier
253*ce95e1b3SDavid du Colombier r = delta = 0; /* to shut compiler up */
254*ce95e1b3SDavid du Colombier if (v) {
255*ce95e1b3SDavid du Colombier r = findsym(v, space, &s);
256*ce95e1b3SDavid du Colombier if (r)
257*ce95e1b3SDavid du Colombier delta = v-s.value;
258*ce95e1b3SDavid du Colombier if (delta < 0)
259*ce95e1b3SDavid du Colombier delta = -delta;
260*ce95e1b3SDavid du Colombier }
261*ce95e1b3SDavid du Colombier if (v == 0 || r == 0 || delta >= 4096)
262*ce95e1b3SDavid du Colombier return snprint(buf, n, "#%lux", v);
263*ce95e1b3SDavid du Colombier if (strcmp(s.name, ".string") == 0)
264*ce95e1b3SDavid du Colombier return snprint(buf, n, "#%lux", v);
265*ce95e1b3SDavid du Colombier if (!delta)
266*ce95e1b3SDavid du Colombier return snprint(buf, n, "%s", s.name);
267*ce95e1b3SDavid du Colombier if (s.type != 't' && s.type != 'T')
268*ce95e1b3SDavid du Colombier return snprint(buf, n, "%s+%llux", s.name, v-s.value);
269*ce95e1b3SDavid du Colombier else
270*ce95e1b3SDavid du Colombier return snprint(buf, n, "#%lux", v);
271*ce95e1b3SDavid du Colombier }
272*ce95e1b3SDavid du Colombier
273*ce95e1b3SDavid du Colombier #pragma varargck argpos bprint 2
274*ce95e1b3SDavid du Colombier
275*ce95e1b3SDavid du Colombier static void
bprint(Instr * i,char * fmt,...)276*ce95e1b3SDavid du Colombier bprint(Instr *i, char *fmt, ...)
277*ce95e1b3SDavid du Colombier {
278*ce95e1b3SDavid du Colombier va_list arg;
279*ce95e1b3SDavid du Colombier
280*ce95e1b3SDavid du Colombier va_start(arg, fmt);
281*ce95e1b3SDavid du Colombier i->curr = vseprint(i->curr, i->end, fmt, arg);
282*ce95e1b3SDavid du Colombier va_end(arg);
283*ce95e1b3SDavid du Colombier }
284*ce95e1b3SDavid du Colombier
285*ce95e1b3SDavid du Colombier static void
format(Instr * i,char * opcode,char * f)286*ce95e1b3SDavid du Colombier format(Instr *i, char *opcode, char *f)
287*ce95e1b3SDavid du Colombier {
288*ce95e1b3SDavid du Colombier int c;
289*ce95e1b3SDavid du Colombier long imm;
290*ce95e1b3SDavid du Colombier char reg;
291*ce95e1b3SDavid du Colombier
292*ce95e1b3SDavid du Colombier reg = 'R';
293*ce95e1b3SDavid du Colombier if(opcode != nil){
294*ce95e1b3SDavid du Colombier bprint(i, "%s", opcode);
295*ce95e1b3SDavid du Colombier if(f == 0)
296*ce95e1b3SDavid du Colombier return;
297*ce95e1b3SDavid du Colombier bprint(i, "\t");
298*ce95e1b3SDavid du Colombier }else
299*ce95e1b3SDavid du Colombier bprint(i, "C.");
300*ce95e1b3SDavid du Colombier for(; (c = *f); f++){
301*ce95e1b3SDavid du Colombier switch(c){
302*ce95e1b3SDavid du Colombier default:
303*ce95e1b3SDavid du Colombier bprint(i, "%c", c);
304*ce95e1b3SDavid du Colombier break;
305*ce95e1b3SDavid du Colombier case ' ':
306*ce95e1b3SDavid du Colombier bprint(i, "\t");
307*ce95e1b3SDavid du Colombier break;
308*ce95e1b3SDavid du Colombier case 'f':
309*ce95e1b3SDavid du Colombier reg = 'F';
310*ce95e1b3SDavid du Colombier break;
311*ce95e1b3SDavid du Colombier case 'j':
312*ce95e1b3SDavid du Colombier reg = '$';
313*ce95e1b3SDavid du Colombier break;
314*ce95e1b3SDavid du Colombier case 's':
315*ce95e1b3SDavid du Colombier bprint(i, "%c%d", reg, i->rs1);
316*ce95e1b3SDavid du Colombier reg = 'R';
317*ce95e1b3SDavid du Colombier break;
318*ce95e1b3SDavid du Colombier case '2':
319*ce95e1b3SDavid du Colombier bprint(i, "%c%d", reg, i->rs2);
320*ce95e1b3SDavid du Colombier reg = 'R';
321*ce95e1b3SDavid du Colombier break;
322*ce95e1b3SDavid du Colombier case '3':
323*ce95e1b3SDavid du Colombier bprint(i, "%c%d", reg, i->rs3);
324*ce95e1b3SDavid du Colombier break;
325*ce95e1b3SDavid du Colombier case 'd':
326*ce95e1b3SDavid du Colombier bprint(i, "%c%d", reg, i->rd);
327*ce95e1b3SDavid du Colombier reg = 'R';
328*ce95e1b3SDavid du Colombier break;
329*ce95e1b3SDavid du Colombier case 'i':
330*ce95e1b3SDavid du Colombier imm = i->imm;
331*ce95e1b3SDavid du Colombier if(imm < 0)
332*ce95e1b3SDavid du Colombier bprint(i, "-%lux", -imm);
333*ce95e1b3SDavid du Colombier else
334*ce95e1b3SDavid du Colombier bprint(i, "%lux", imm);
335*ce95e1b3SDavid du Colombier break;
336*ce95e1b3SDavid du Colombier case 'p':
337*ce95e1b3SDavid du Colombier imm = i->addr + i->imm;
338*ce95e1b3SDavid du Colombier i->curr += gsymoff(i->curr, i->end-i->curr, imm, CANY);
339*ce95e1b3SDavid du Colombier break;
340*ce95e1b3SDavid du Colombier case 'a':
341*ce95e1b3SDavid du Colombier if(i->rs1 == REGSB && mach->sb){
342*ce95e1b3SDavid du Colombier i->curr += gsymoff(i->curr, i->end-i->curr, i->imm+mach->sb, CANY);
343*ce95e1b3SDavid du Colombier bprint(i, "(SB)");
344*ce95e1b3SDavid du Colombier break;
345*ce95e1b3SDavid du Colombier }
346*ce95e1b3SDavid du Colombier bprint(i, "%lx(R%d)", i->imm, i->rs1);
347*ce95e1b3SDavid du Colombier break;
348*ce95e1b3SDavid du Colombier case '7':
349*ce95e1b3SDavid du Colombier bprint(i, "%ux", i->func7);
350*ce95e1b3SDavid du Colombier break;
351*ce95e1b3SDavid du Colombier case 'c':
352*ce95e1b3SDavid du Colombier bprint(i, "CSR(%lx)", i->imm&0xFFF);
353*ce95e1b3SDavid du Colombier break;
354*ce95e1b3SDavid du Colombier }
355*ce95e1b3SDavid du Colombier }
356*ce95e1b3SDavid du Colombier }
357*ce95e1b3SDavid du Colombier
358*ce95e1b3SDavid du Colombier static int
badinst(Instr * i)359*ce95e1b3SDavid du Colombier badinst(Instr *i)
360*ce95e1b3SDavid du Colombier {
361*ce95e1b3SDavid du Colombier format(i, "???", 0);
362*ce95e1b3SDavid du Colombier return 4;
363*ce95e1b3SDavid du Colombier }
364*ce95e1b3SDavid du Colombier
365*ce95e1b3SDavid du Colombier static long
immshuffle(uint w,uchar * p)366*ce95e1b3SDavid du Colombier immshuffle(uint w, uchar *p)
367*ce95e1b3SDavid du Colombier {
368*ce95e1b3SDavid du Colombier int shift, i;
369*ce95e1b3SDavid du Colombier ulong imm;
370*ce95e1b3SDavid du Colombier
371*ce95e1b3SDavid du Colombier shift = *p++;
372*ce95e1b3SDavid du Colombier imm = 0;
373*ce95e1b3SDavid du Colombier while((i = *p++) != 0){
374*ce95e1b3SDavid du Colombier imm >>= 1;
375*ce95e1b3SDavid du Colombier if((w>>i) & 0x01)
376*ce95e1b3SDavid du Colombier imm |= (1<<31);
377*ce95e1b3SDavid du Colombier }
378*ce95e1b3SDavid du Colombier if(shift & 0x80)
379*ce95e1b3SDavid du Colombier imm = (long)imm >> (shift ^ 0xFF);
380*ce95e1b3SDavid du Colombier else
381*ce95e1b3SDavid du Colombier imm >>= shift;
382*ce95e1b3SDavid du Colombier return imm;
383*ce95e1b3SDavid du Colombier }
384*ce95e1b3SDavid du Colombier
385*ce95e1b3SDavid du Colombier static int
decompress(Instr * i)386*ce95e1b3SDavid du Colombier decompress(Instr *i)
387*ce95e1b3SDavid du Colombier {
388*ce95e1b3SDavid du Colombier ushort w;
389*ce95e1b3SDavid du Colombier int op, aop;
390*ce95e1b3SDavid du Colombier Compclass *cop;
391*ce95e1b3SDavid du Colombier
392*ce95e1b3SDavid du Colombier w = i->w;
393*ce95e1b3SDavid du Colombier i->n = 2;
394*ce95e1b3SDavid du Colombier i->func3 = (w>>13)&0x7;
395*ce95e1b3SDavid du Colombier op = w&0x3;
396*ce95e1b3SDavid du Colombier i->op = op;
397*ce95e1b3SDavid du Colombier switch(op){
398*ce95e1b3SDavid du Colombier case 0:
399*ce95e1b3SDavid du Colombier i->rd = 8 + ((w>>2)&0x7);
400*ce95e1b3SDavid du Colombier i->rs1 = 8 + ((w>>7)&0x7);
401*ce95e1b3SDavid du Colombier i->rs2 = i->rd;
402*ce95e1b3SDavid du Colombier break;
403*ce95e1b3SDavid du Colombier case 1:
404*ce95e1b3SDavid du Colombier i->rd = (w>>7)&0x1F;
405*ce95e1b3SDavid du Colombier if((i->func3&0x4) != 0)
406*ce95e1b3SDavid du Colombier i->rd = 8 + (i->rd&0x7);
407*ce95e1b3SDavid du Colombier i->rs1 = i->rd;
408*ce95e1b3SDavid du Colombier i->rs2 = 8 + ((w>>2)&0x7);
409*ce95e1b3SDavid du Colombier break;
410*ce95e1b3SDavid du Colombier case 2:
411*ce95e1b3SDavid du Colombier i->rd = (w>>7)&0x1F;
412*ce95e1b3SDavid du Colombier i->rs1 = i->rd;
413*ce95e1b3SDavid du Colombier i->rs2 = (w>>2)&0x1F;
414*ce95e1b3SDavid du Colombier }
415*ce95e1b3SDavid du Colombier aop = (op << 3) + i->func3;
416*ce95e1b3SDavid du Colombier if((aop & 0x7) == 4){
417*ce95e1b3SDavid du Colombier switch(op){
418*ce95e1b3SDavid du Colombier case 1:
419*ce95e1b3SDavid du Colombier aop = 0x18 + ((w>>10) & 0x3);
420*ce95e1b3SDavid du Colombier if(aop == 0x1B)
421*ce95e1b3SDavid du Colombier aop += ((w>>10) & 0x4) + ((w>>5) & 0x3);
422*ce95e1b3SDavid du Colombier break;
423*ce95e1b3SDavid du Colombier case 2:
424*ce95e1b3SDavid du Colombier aop = 0x23 + ((w>>11) & 0x2) + (i->rs2 != 0);
425*ce95e1b3SDavid du Colombier if(aop == 0x26 && i->rd == 0)
426*ce95e1b3SDavid du Colombier aop = 0x2D;
427*ce95e1b3SDavid du Colombier break;
428*ce95e1b3SDavid du Colombier }
429*ce95e1b3SDavid du Colombier }
430*ce95e1b3SDavid du Colombier if(aop == 0x0B && i->rd == 2)
431*ce95e1b3SDavid du Colombier aop = 0x27;
432*ce95e1b3SDavid du Colombier if(i->rv64) switch(aop){
433*ce95e1b3SDavid du Colombier case 0x03: aop = 0x28; break;
434*ce95e1b3SDavid du Colombier case 0x07: aop = 0x29; break;
435*ce95e1b3SDavid du Colombier case 0x09: aop = 0x2A; break;
436*ce95e1b3SDavid du Colombier case 0x13: aop = 0x2B; break;
437*ce95e1b3SDavid du Colombier case 0x17: aop = 0x2C; break;
438*ce95e1b3SDavid du Colombier }
439*ce95e1b3SDavid du Colombier i->aop = aop;
440*ce95e1b3SDavid du Colombier cop = &rv32compressed[aop];
441*ce95e1b3SDavid du Colombier i->fmt = cop->fmt;
442*ce95e1b3SDavid du Colombier i->imm = immshuffle(w, cop->immbits);
443*ce95e1b3SDavid du Colombier return 2;
444*ce95e1b3SDavid du Colombier }
445*ce95e1b3SDavid du Colombier
446*ce95e1b3SDavid du Colombier static int
decode(Map * map,uvlong pc,Instr * i)447*ce95e1b3SDavid du Colombier decode(Map *map, uvlong pc, Instr *i)
448*ce95e1b3SDavid du Colombier {
449*ce95e1b3SDavid du Colombier ulong w;
450*ce95e1b3SDavid du Colombier int op;
451*ce95e1b3SDavid du Colombier
452*ce95e1b3SDavid du Colombier if(get4(map, pc, &w) < 0) {
453*ce95e1b3SDavid du Colombier werrstr("can't read instruction: %r");
454*ce95e1b3SDavid du Colombier return -1;
455*ce95e1b3SDavid du Colombier }
456*ce95e1b3SDavid du Colombier i->addr = pc;
457*ce95e1b3SDavid du Colombier i->map = map;
458*ce95e1b3SDavid du Colombier if((w&0x3) != 3){
459*ce95e1b3SDavid du Colombier i->w = w & 0xFFFF;
460*ce95e1b3SDavid du Colombier return decompress(i);
461*ce95e1b3SDavid du Colombier }
462*ce95e1b3SDavid du Colombier i->w = w;
463*ce95e1b3SDavid du Colombier i->n = 4;
464*ce95e1b3SDavid du Colombier op = (w&0x7F);
465*ce95e1b3SDavid du Colombier i->op = op;
466*ce95e1b3SDavid du Colombier i->func3 = (w>>12)&0x7;
467*ce95e1b3SDavid du Colombier i->func7 = (w>>25)&0x7F;
468*ce95e1b3SDavid du Colombier i->rs1 = (w>>15)&0x1F;
469*ce95e1b3SDavid du Colombier i->rs2 = (w>>20)&0x1F;
470*ce95e1b3SDavid du Colombier i->rs3 = (w>>27)&0x1F;
471*ce95e1b3SDavid du Colombier i->rd = (w>>7)&0x1F;
472*ce95e1b3SDavid du Colombier #define FIELD(hi,lo,off) (w>>(lo-off))&(((1<<(hi-lo+1))-1)<<off)
473*ce95e1b3SDavid du Colombier #define LFIELD(hi,lo,off) (w<<(off-lo))&(((1<<(hi-lo+1))-1)<<off)
474*ce95e1b3SDavid du Colombier #define SFIELD(lo,off) ((long)(w&((~0)<<lo))>>(lo-off))
475*ce95e1b3SDavid du Colombier switch(op>>2) {
476*ce95e1b3SDavid du Colombier case OSTORE: /* S-type */
477*ce95e1b3SDavid du Colombier case OSTORE_FP:
478*ce95e1b3SDavid du Colombier i->imm = SFIELD(25,5) | FIELD(11,7,0);
479*ce95e1b3SDavid du Colombier break;
480*ce95e1b3SDavid du Colombier case OBRANCH: /* B-type */
481*ce95e1b3SDavid du Colombier i->imm = SFIELD(31,12) | LFIELD(7,7,11) | FIELD(30,25,5) | FIELD(11,8,1);
482*ce95e1b3SDavid du Colombier break;
483*ce95e1b3SDavid du Colombier case OOP_IMM: /* I-type */
484*ce95e1b3SDavid du Colombier case OOP_IMM_32:
485*ce95e1b3SDavid du Colombier if(i->func3 == 1 || i->func3 == 5){ /* special case ASL/ASR */
486*ce95e1b3SDavid du Colombier i->imm = FIELD(25,20,0);
487*ce95e1b3SDavid du Colombier break;
488*ce95e1b3SDavid du Colombier }
489*ce95e1b3SDavid du Colombier /* fall through */
490*ce95e1b3SDavid du Colombier case OLOAD:
491*ce95e1b3SDavid du Colombier case OLOAD_FP:
492*ce95e1b3SDavid du Colombier case OMISC_MEM:
493*ce95e1b3SDavid du Colombier case OJALR:
494*ce95e1b3SDavid du Colombier case OSYSTEM:
495*ce95e1b3SDavid du Colombier i->imm = SFIELD(20,0);
496*ce95e1b3SDavid du Colombier break;
497*ce95e1b3SDavid du Colombier case OAUIPC: /* U-type */
498*ce95e1b3SDavid du Colombier case OLUI:
499*ce95e1b3SDavid du Colombier i->imm = SFIELD(12,12);
500*ce95e1b3SDavid du Colombier break;
501*ce95e1b3SDavid du Colombier case OJAL: /* J-type */
502*ce95e1b3SDavid du Colombier i->imm = SFIELD(31,20) | FIELD(19,12,12) | FIELD(20,20,11) | FIELD(30,21,1);
503*ce95e1b3SDavid du Colombier break;
504*ce95e1b3SDavid du Colombier }
505*ce95e1b3SDavid du Colombier return 4;
506*ce95e1b3SDavid du Colombier }
507*ce95e1b3SDavid du Colombier
508*ce95e1b3SDavid du Colombier static int
pseudo(Instr * i,int aop)509*ce95e1b3SDavid du Colombier pseudo(Instr *i, int aop)
510*ce95e1b3SDavid du Colombier {
511*ce95e1b3SDavid du Colombier char *op;
512*ce95e1b3SDavid du Colombier
513*ce95e1b3SDavid du Colombier switch(aop){
514*ce95e1b3SDavid du Colombier case AJAL:
515*ce95e1b3SDavid du Colombier if(i->rd == 0){
516*ce95e1b3SDavid du Colombier format(i, "JMP", "p");
517*ce95e1b3SDavid du Colombier return 1;
518*ce95e1b3SDavid du Colombier }
519*ce95e1b3SDavid du Colombier break;
520*ce95e1b3SDavid du Colombier case AJALR:
521*ce95e1b3SDavid du Colombier if(i->rd == 0){
522*ce95e1b3SDavid du Colombier format(i, "JMP", "a");
523*ce95e1b3SDavid du Colombier return 1;
524*ce95e1b3SDavid du Colombier }
525*ce95e1b3SDavid du Colombier break;
526*ce95e1b3SDavid du Colombier case AADD:
527*ce95e1b3SDavid du Colombier if((i->op>>2) == OOP_IMM){
528*ce95e1b3SDavid du Colombier op = i->rv64 ? "MOV" : "MOVW";
529*ce95e1b3SDavid du Colombier if(i->rs1 == 0)
530*ce95e1b3SDavid du Colombier format(i, op, "$i,d");
531*ce95e1b3SDavid du Colombier else if(i->rs1 == REGSB && mach->sb && i->rd != REGSB)
532*ce95e1b3SDavid du Colombier format(i, op, "$a,d");
533*ce95e1b3SDavid du Colombier else if(i->imm == 0)
534*ce95e1b3SDavid du Colombier format(i, op, "s,d");
535*ce95e1b3SDavid du Colombier else break;
536*ce95e1b3SDavid du Colombier return 1;
537*ce95e1b3SDavid du Colombier }
538*ce95e1b3SDavid du Colombier break;
539*ce95e1b3SDavid du Colombier case ASYS:
540*ce95e1b3SDavid du Colombier switch(i->imm){
541*ce95e1b3SDavid du Colombier case 0:
542*ce95e1b3SDavid du Colombier format(i, "ECALL", nil);
543*ce95e1b3SDavid du Colombier return 1;
544*ce95e1b3SDavid du Colombier case 1:
545*ce95e1b3SDavid du Colombier format(i, "EBREAK", nil);
546*ce95e1b3SDavid du Colombier return 1;
547*ce95e1b3SDavid du Colombier }
548*ce95e1b3SDavid du Colombier }
549*ce95e1b3SDavid du Colombier return 0;
550*ce95e1b3SDavid du Colombier }
551*ce95e1b3SDavid du Colombier
552*ce95e1b3SDavid du Colombier static int
mkinstr(Instr * i)553*ce95e1b3SDavid du Colombier mkinstr(Instr *i)
554*ce95e1b3SDavid du Colombier {
555*ce95e1b3SDavid du Colombier Opclass *oc;
556*ce95e1b3SDavid du Colombier Optab *o;
557*ce95e1b3SDavid du Colombier char *fmt;
558*ce95e1b3SDavid du Colombier int aop;
559*ce95e1b3SDavid du Colombier
560*ce95e1b3SDavid du Colombier if((i->op&0x3) != 0x3){
561*ce95e1b3SDavid du Colombier format(i, nil, i->fmt);
562*ce95e1b3SDavid du Colombier return 2;
563*ce95e1b3SDavid du Colombier }
564*ce95e1b3SDavid du Colombier oc = opclass[i->op>>2];
565*ce95e1b3SDavid du Colombier if(oc == 0)
566*ce95e1b3SDavid du Colombier return badinst(i);
567*ce95e1b3SDavid du Colombier fmt = oc->fmt;
568*ce95e1b3SDavid du Colombier if(oc == &opOSYSTEM)
569*ce95e1b3SDavid du Colombier fmt = fmtOSYSTEM[i->func3];
570*ce95e1b3SDavid du Colombier if(oc == &opOOP_FP){
571*ce95e1b3SDavid du Colombier if(i->func7 & 1)
572*ce95e1b3SDavid du Colombier oc = &opOOP_DP;
573*ce95e1b3SDavid du Colombier o = &oc->tab[i->func7>>5];
574*ce95e1b3SDavid du Colombier switch(o->func7){
575*ce95e1b3SDavid du Colombier case 0:
576*ce95e1b3SDavid du Colombier fmt = "f2,fs,fd";
577*ce95e1b3SDavid du Colombier /* fall through */
578*ce95e1b3SDavid du Colombier default:
579*ce95e1b3SDavid du Colombier aop = o->op[(i->func7>>2)&0x7];
580*ce95e1b3SDavid du Colombier if((i->func7&~1) == 0x10){
581*ce95e1b3SDavid du Colombier if(i->func3 == 0 && i->rs1 == i->rs2)
582*ce95e1b3SDavid du Colombier fmt = "fs,fd";
583*ce95e1b3SDavid du Colombier else
584*ce95e1b3SDavid du Colombier aop = 0;
585*ce95e1b3SDavid du Colombier }
586*ce95e1b3SDavid du Colombier break;
587*ce95e1b3SDavid du Colombier case 2:
588*ce95e1b3SDavid du Colombier aop = o->op[i->func3];
589*ce95e1b3SDavid du Colombier break;
590*ce95e1b3SDavid du Colombier case 3:
591*ce95e1b3SDavid du Colombier if(i->func7 & 0x10)
592*ce95e1b3SDavid du Colombier return badinst(i);
593*ce95e1b3SDavid du Colombier aop = o->op[(i->func7>>1)&0x4 | (i->rs2&0x3)];
594*ce95e1b3SDavid du Colombier if(i->func7 & 0x8)
595*ce95e1b3SDavid du Colombier fmt = "s,fd";
596*ce95e1b3SDavid du Colombier else
597*ce95e1b3SDavid du Colombier fmt = "fs,d";
598*ce95e1b3SDavid du Colombier break;
599*ce95e1b3SDavid du Colombier }
600*ce95e1b3SDavid du Colombier if(aop == 0)
601*ce95e1b3SDavid du Colombier return badinst(i);
602*ce95e1b3SDavid du Colombier format(i, anames[aop], fmt);
603*ce95e1b3SDavid du Colombier return 4;
604*ce95e1b3SDavid du Colombier }
605*ce95e1b3SDavid du Colombier o = oc->tab;
606*ce95e1b3SDavid du Colombier while(o->func7 != 0 && (i->func7 != o->func7 || o->op[i->func3] == 0))
607*ce95e1b3SDavid du Colombier o++;
608*ce95e1b3SDavid du Colombier if((aop = o->op[i->func3]) == 0)
609*ce95e1b3SDavid du Colombier return badinst(i);
610*ce95e1b3SDavid du Colombier if(pseudo(i, aop))
611*ce95e1b3SDavid du Colombier return 4;
612*ce95e1b3SDavid du Colombier format(i, anames[aop], fmt);
613*ce95e1b3SDavid du Colombier return 4;
614*ce95e1b3SDavid du Colombier }
615*ce95e1b3SDavid du Colombier
616*ce95e1b3SDavid du Colombier static int
riscvdas(Map * map,uvlong pc,char modifier,char * buf,int n)617*ce95e1b3SDavid du Colombier riscvdas(Map *map, uvlong pc, char modifier, char *buf, int n)
618*ce95e1b3SDavid du Colombier {
619*ce95e1b3SDavid du Colombier Instr i;
620*ce95e1b3SDavid du Colombier
621*ce95e1b3SDavid du Colombier USED(modifier);
622*ce95e1b3SDavid du Colombier i.rv64 = 0;
623*ce95e1b3SDavid du Colombier i.curr = buf;
624*ce95e1b3SDavid du Colombier i.end = buf+n;
625*ce95e1b3SDavid du Colombier if(decode(map, pc, &i) < 0)
626*ce95e1b3SDavid du Colombier return -1;
627*ce95e1b3SDavid du Colombier return mkinstr(&i);
628*ce95e1b3SDavid du Colombier }
629*ce95e1b3SDavid du Colombier
630*ce95e1b3SDavid du Colombier static int
riscv64das(Map * map,uvlong pc,char modifier,char * buf,int n)631*ce95e1b3SDavid du Colombier riscv64das(Map *map, uvlong pc, char modifier, char *buf, int n)
632*ce95e1b3SDavid du Colombier {
633*ce95e1b3SDavid du Colombier Instr i;
634*ce95e1b3SDavid du Colombier
635*ce95e1b3SDavid du Colombier USED(modifier);
636*ce95e1b3SDavid du Colombier i.rv64 = 1;
637*ce95e1b3SDavid du Colombier i.curr = buf;
638*ce95e1b3SDavid du Colombier i.end = buf+n;
639*ce95e1b3SDavid du Colombier if(decode(map, pc, &i) < 0)
640*ce95e1b3SDavid du Colombier return -1;
641*ce95e1b3SDavid du Colombier return mkinstr(&i);
642*ce95e1b3SDavid du Colombier }
643*ce95e1b3SDavid du Colombier
644*ce95e1b3SDavid du Colombier static int
riscvhexinst(Map * map,uvlong pc,char * buf,int n)645*ce95e1b3SDavid du Colombier riscvhexinst(Map *map, uvlong pc, char *buf, int n)
646*ce95e1b3SDavid du Colombier {
647*ce95e1b3SDavid du Colombier Instr i;
648*ce95e1b3SDavid du Colombier
649*ce95e1b3SDavid du Colombier i.curr = buf;
650*ce95e1b3SDavid du Colombier i.end = buf+n;
651*ce95e1b3SDavid du Colombier if(decode(map, pc, &i) < 0)
652*ce95e1b3SDavid du Colombier return -1;
653*ce95e1b3SDavid du Colombier if(i.end-i.curr > 2*i.n)
654*ce95e1b3SDavid du Colombier i.curr = _hexify(buf, i.w, 2*i.n - 1);
655*ce95e1b3SDavid du Colombier *i.curr = 0;
656*ce95e1b3SDavid du Colombier return i.n;
657*ce95e1b3SDavid du Colombier }
658*ce95e1b3SDavid du Colombier
659*ce95e1b3SDavid du Colombier static int
riscvinstlen(Map * map,uvlong pc)660*ce95e1b3SDavid du Colombier riscvinstlen(Map *map, uvlong pc)
661*ce95e1b3SDavid du Colombier {
662*ce95e1b3SDavid du Colombier Instr i;
663*ce95e1b3SDavid du Colombier
664*ce95e1b3SDavid du Colombier return decode(map, pc, &i);
665*ce95e1b3SDavid du Colombier }
666*ce95e1b3SDavid du Colombier
667*ce95e1b3SDavid du Colombier static char*
riscvexcep(Map *,Rgetter)668*ce95e1b3SDavid du Colombier riscvexcep(Map*, Rgetter)
669*ce95e1b3SDavid du Colombier {
670*ce95e1b3SDavid du Colombier return "Trap";
671*ce95e1b3SDavid du Colombier }
672*ce95e1b3SDavid du Colombier
673*ce95e1b3SDavid du Colombier static int
riscvfoll(Map * map,uvlong pc,Rgetter rget,uvlong * foll)674*ce95e1b3SDavid du Colombier riscvfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
675*ce95e1b3SDavid du Colombier {
676*ce95e1b3SDavid du Colombier Instr i;
677*ce95e1b3SDavid du Colombier char buf[8];
678*ce95e1b3SDavid du Colombier int len;
679*ce95e1b3SDavid du Colombier
680*ce95e1b3SDavid du Colombier len = decode(map, pc, &i);
681*ce95e1b3SDavid du Colombier if(len < 0)
682*ce95e1b3SDavid du Colombier return -1;
683*ce95e1b3SDavid du Colombier foll[0] = pc + len;
684*ce95e1b3SDavid du Colombier if(len == 2){
685*ce95e1b3SDavid du Colombier switch(i.aop){
686*ce95e1b3SDavid du Colombier case 0x0D: /* C.J */
687*ce95e1b3SDavid du Colombier case 0x0E: /* C.BEQZ */
688*ce95e1b3SDavid du Colombier case 0x0F: /* C.BNEZ */
689*ce95e1b3SDavid du Colombier foll[1] = pc + i.imm;
690*ce95e1b3SDavid du Colombier return 2;
691*ce95e1b3SDavid du Colombier case 0x09: /* C.JAL */
692*ce95e1b3SDavid du Colombier foll[0] = pc + i.imm;
693*ce95e1b3SDavid du Colombier break;
694*ce95e1b3SDavid du Colombier case 0x23: /* C.JR */
695*ce95e1b3SDavid du Colombier case 0x25: /* C.JALR */
696*ce95e1b3SDavid du Colombier sprint(buf, "R%d", i.rs1);
697*ce95e1b3SDavid du Colombier foll[0] = (*rget)(map, buf);
698*ce95e1b3SDavid du Colombier break;
699*ce95e1b3SDavid du Colombier }
700*ce95e1b3SDavid du Colombier return 1;
701*ce95e1b3SDavid du Colombier }
702*ce95e1b3SDavid du Colombier switch(i.op>>2) {
703*ce95e1b3SDavid du Colombier case OBRANCH:
704*ce95e1b3SDavid du Colombier foll[1] = pc + i.imm;
705*ce95e1b3SDavid du Colombier return 2;
706*ce95e1b3SDavid du Colombier case OJAL:
707*ce95e1b3SDavid du Colombier foll[0] = pc + i.imm;
708*ce95e1b3SDavid du Colombier break;
709*ce95e1b3SDavid du Colombier case OJALR:
710*ce95e1b3SDavid du Colombier sprint(buf, "R%d", i.rd);
711*ce95e1b3SDavid du Colombier foll[0] = (*rget)(map, buf);
712*ce95e1b3SDavid du Colombier break;
713*ce95e1b3SDavid du Colombier }
714*ce95e1b3SDavid du Colombier return 1;
715*ce95e1b3SDavid du Colombier }
716*ce95e1b3SDavid du Colombier
717*ce95e1b3SDavid du Colombier /*
718*ce95e1b3SDavid du Colombier * Debugger interface
719*ce95e1b3SDavid du Colombier */
720*ce95e1b3SDavid du Colombier Machdata riscvmach =
721*ce95e1b3SDavid du Colombier {
722*ce95e1b3SDavid du Colombier {0x02, 0x90}, /* break point */
723*ce95e1b3SDavid du Colombier 2, /* break point size */
724*ce95e1b3SDavid du Colombier
725*ce95e1b3SDavid du Colombier leswab, /* short to local byte order */
726*ce95e1b3SDavid du Colombier leswal, /* long to local byte order */
727*ce95e1b3SDavid du Colombier leswav, /* long to local byte order */
728*ce95e1b3SDavid du Colombier risctrace, /* C traceback */
729*ce95e1b3SDavid du Colombier riscframe, /* Frame finder */
730*ce95e1b3SDavid du Colombier riscvexcep, /* print exception */
731*ce95e1b3SDavid du Colombier 0, /* breakpoint fixup */
732*ce95e1b3SDavid du Colombier 0, /* single precision float printer */
733*ce95e1b3SDavid du Colombier 0, /* double precisioin float printer */
734*ce95e1b3SDavid du Colombier riscvfoll, /* following addresses */
735*ce95e1b3SDavid du Colombier riscvdas, /* symbolic disassembly */
736*ce95e1b3SDavid du Colombier riscvhexinst, /* hex disassembly */
737*ce95e1b3SDavid du Colombier riscvinstlen, /* instruction size */
738*ce95e1b3SDavid du Colombier };
739*ce95e1b3SDavid du Colombier
740*ce95e1b3SDavid du Colombier Machdata riscv64mach =
741*ce95e1b3SDavid du Colombier {
742*ce95e1b3SDavid du Colombier {0x02, 0x90}, /* break point */
743*ce95e1b3SDavid du Colombier 2, /* break point size */
744*ce95e1b3SDavid du Colombier
745*ce95e1b3SDavid du Colombier leswab, /* short to local byte order */
746*ce95e1b3SDavid du Colombier leswal, /* long to local byte order */
747*ce95e1b3SDavid du Colombier leswav, /* long to local byte order */
748*ce95e1b3SDavid du Colombier risctrace, /* C traceback */
749*ce95e1b3SDavid du Colombier riscframe, /* Frame finder */
750*ce95e1b3SDavid du Colombier riscvexcep, /* print exception */
751*ce95e1b3SDavid du Colombier 0, /* breakpoint fixup */
752*ce95e1b3SDavid du Colombier 0, /* single precision float printer */
753*ce95e1b3SDavid du Colombier 0, /* double precisioin float printer */
754*ce95e1b3SDavid du Colombier riscvfoll, /* following addresses */
755*ce95e1b3SDavid du Colombier riscv64das, /* symbolic disassembly */
756*ce95e1b3SDavid du Colombier riscvhexinst, /* hex disassembly */
757*ce95e1b3SDavid du Colombier riscvinstlen, /* instruction size */
758*ce95e1b3SDavid du Colombier };
759