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