1 /* $NetBSD: db_interface.c,v 1.42 2002/03/11 16:39:40 uch Exp $ */ 2 3 /* 4 * Mach Operating System 5 * Copyright (c) 1991,1990 Carnegie Mellon University 6 * All Rights Reserved. 7 * 8 * Permission to use, copy, modify and distribute this software and its 9 * documentation is hereby granted, provided that both the copyright 10 * notice and this permission notice appear in all copies of the 11 * software, derivative works or modified versions, and any portions 12 * thereof, and that both notices appear in supporting documentation. 13 * 14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 17 * 18 * Carnegie Mellon requests users of this software to return to 19 * 20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 21 * School of Computer Science 22 * Carnegie Mellon University 23 * Pittsburgh PA 15213-3890 24 * 25 * any improvements or extensions that they make and grant Carnegie Mellon 26 * the rights to redistribute these changes. 27 */ 28 29 #include "opt_cputype.h" /* which mips CPUs do we support? */ 30 #include "opt_ddb.h" 31 #include "opt_kgdb.h" 32 33 #include <sys/types.h> 34 #include <sys/systm.h> 35 #include <sys/param.h> 36 #include <sys/proc.h> 37 #include <sys/user.h> 38 #include <sys/reboot.h> 39 40 #include <uvm/uvm_extern.h> 41 42 #include <mips/cache.h> 43 #include <mips/pte.h> 44 #include <mips/cpu.h> 45 #include <mips/locore.h> 46 #include <mips/mips_opcode.h> 47 #include <dev/cons.h> 48 49 #include <machine/db_machdep.h> 50 #include <ddb/db_access.h> 51 #ifndef KGDB 52 #include <ddb/db_command.h> 53 #include <ddb/db_output.h> 54 #include <ddb/db_sym.h> 55 #include <ddb/db_extern.h> 56 #include <ddb/db_interface.h> 57 #endif 58 59 int db_active = 0; 60 db_regs_t ddb_regs; 61 mips_reg_t kdbaux[11]; /* XXX struct switchframe: better inside curpcb? XXX */ 62 63 void db_tlbdump_cmd(db_expr_t, int, db_expr_t, char *); 64 void db_kvtophys_cmd(db_expr_t, int, db_expr_t, char *); 65 void db_cp0dump_cmd(db_expr_t, int, db_expr_t, char *); 66 67 static void kdbpoke_4(vaddr_t addr, int newval); 68 static void kdbpoke_2(vaddr_t addr, short newval); 69 static void kdbpoke_1(vaddr_t addr, char newval); 70 static short kdbpeek_2(vaddr_t addr); 71 static char kdbpeek_1(vaddr_t addr); 72 extern vaddr_t MachEmulateBranch(struct frame *, vaddr_t, unsigned, int); 73 74 extern paddr_t kvtophys(vaddr_t); 75 76 #ifdef DDB_TRACE 77 int 78 kdbpeek(vaddr_t addr) 79 { 80 81 if (addr == 0 || (addr & 3)) 82 return 0; 83 return *(int *)addr; 84 } 85 #endif 86 87 static short 88 kdbpeek_2(vaddr_t addr) 89 { 90 91 return *(short *)addr; 92 } 93 94 static char 95 kdbpeek_1(vaddr_t addr) 96 { 97 98 return *(char *)addr; 99 } 100 101 /* 102 * kdbpoke -- write a value to a kernel virtual address. 103 * XXX should handle KSEG2 addresses and check for unmapped pages. 104 * XXX user-space addresess? 105 */ 106 static void 107 kdbpoke_4(vaddr_t addr, int newval) 108 { 109 110 *(int*) addr = newval; 111 wbflush(); 112 } 113 114 static void 115 kdbpoke_2(vaddr_t addr, short newval) 116 { 117 118 *(short*) addr = newval; 119 wbflush(); 120 } 121 122 static void 123 kdbpoke_1(vaddr_t addr, char newval) 124 { 125 *(char*) addr = newval; 126 wbflush(); 127 } 128 129 #if 0 /* UNUSED */ 130 /* 131 * Received keyboard interrupt sequence. 132 */ 133 void 134 kdb_kbd_trap(int *tf) 135 { 136 137 if (db_active == 0 && (boothowto & RB_KDB)) { 138 printf("\n\nkernel: keyboard interrupt\n"); 139 ddb_trap(-1, tf); 140 } 141 } 142 #endif 143 144 #ifndef KGDB 145 int 146 kdb_trap(int type, mips_reg_t /* struct trapframe */ *tfp) 147 { 148 149 struct frame *f = (struct frame *)&ddb_regs; 150 151 #ifdef notyet 152 switch (type) { 153 case T_BREAK: /* breakpoint */ 154 case -1: /* keyboard interrupt */ 155 break; 156 default: 157 printf("kernel: %s trap", trap_type[type & 0xff]); 158 if (db_recover != 0) { 159 db_error("Faulted in DDB; continuing...\n"); 160 /*NOTREACHED*/ 161 } 162 break; 163 } 164 #endif 165 /* Should switch to kdb`s own stack here. */ 166 db_set_ddb_regs(type, tfp); 167 168 db_active++; 169 cnpollc(1); 170 db_trap(type & ~T_USER, 0 /*code*/); 171 cnpollc(0); 172 db_active--; 173 174 if (type & T_USER) 175 *(struct frame *)curproc->p_md.md_regs = *f; 176 else { 177 /* Synthetic full scale register context when trap happens */ 178 tfp[0] = f->f_regs[AST]; 179 tfp[1] = f->f_regs[V0]; 180 tfp[2] = f->f_regs[V1]; 181 tfp[3] = f->f_regs[A0]; 182 tfp[4] = f->f_regs[A1]; 183 tfp[5] = f->f_regs[A2]; 184 tfp[6] = f->f_regs[A3]; 185 tfp[7] = f->f_regs[T0]; 186 tfp[8] = f->f_regs[T1]; 187 tfp[9] = f->f_regs[T2]; 188 tfp[10] = f->f_regs[T3]; 189 tfp[11] = f->f_regs[T4]; 190 tfp[12] = f->f_regs[T5]; 191 tfp[13] = f->f_regs[T6]; 192 tfp[14] = f->f_regs[T7]; 193 tfp[15] = f->f_regs[T8]; 194 tfp[16] = f->f_regs[T9]; 195 tfp[17] = f->f_regs[RA]; 196 tfp[18] = f->f_regs[SR]; 197 tfp[19] = f->f_regs[MULLO]; 198 tfp[20] = f->f_regs[MULHI]; 199 tfp[21] = f->f_regs[PC]; 200 kdbaux[0] = f->f_regs[S0]; 201 kdbaux[1] = f->f_regs[S1]; 202 kdbaux[2] = f->f_regs[S2]; 203 kdbaux[3] = f->f_regs[S3]; 204 kdbaux[4] = f->f_regs[S4]; 205 kdbaux[5] = f->f_regs[S5]; 206 kdbaux[6] = f->f_regs[S6]; 207 kdbaux[7] = f->f_regs[S7]; 208 kdbaux[8] = f->f_regs[SP]; 209 kdbaux[9] = f->f_regs[S8]; 210 kdbaux[10] = f->f_regs[GP]; 211 } 212 213 return (1); 214 } 215 216 void 217 cpu_Debugger(void) 218 { 219 220 asm("break"); 221 } 222 #endif /* !KGDB */ 223 224 void 225 db_set_ddb_regs(int type, mips_reg_t *tfp) 226 { 227 struct frame *f = (struct frame *)&ddb_regs; 228 229 /* Should switch to kdb`s own stack here. */ 230 231 if (type & T_USER) 232 *f = *(struct frame *)curproc->p_md.md_regs; 233 else { 234 /* Synthetic full scale register context when trap happens */ 235 f->f_regs[AST] = tfp[0]; 236 f->f_regs[V0] = tfp[1]; 237 f->f_regs[V1] = tfp[2]; 238 f->f_regs[A0] = tfp[3]; 239 f->f_regs[A1] = tfp[4]; 240 f->f_regs[A2] = tfp[5]; 241 f->f_regs[A3] = tfp[6]; 242 f->f_regs[T0] = tfp[7]; 243 f->f_regs[T1] = tfp[8]; 244 f->f_regs[T2] = tfp[9]; 245 f->f_regs[T3] = tfp[10]; 246 f->f_regs[T4] = tfp[11]; 247 f->f_regs[T5] = tfp[12]; 248 f->f_regs[T6] = tfp[13]; 249 f->f_regs[T7] = tfp[14]; 250 f->f_regs[T8] = tfp[15]; 251 f->f_regs[T9] = tfp[16]; 252 f->f_regs[RA] = tfp[17]; 253 f->f_regs[SR] = tfp[18]; 254 f->f_regs[MULLO] = tfp[19]; 255 f->f_regs[MULHI] = tfp[20]; 256 f->f_regs[PC] = tfp[21]; 257 f->f_regs[S0] = kdbaux[0]; 258 f->f_regs[S1] = kdbaux[1]; 259 f->f_regs[S2] = kdbaux[2]; 260 f->f_regs[S3] = kdbaux[3]; 261 f->f_regs[S4] = kdbaux[4]; 262 f->f_regs[S5] = kdbaux[5]; 263 f->f_regs[S6] = kdbaux[6]; 264 f->f_regs[S7] = kdbaux[7]; 265 f->f_regs[SP] = kdbaux[8]; 266 f->f_regs[S8] = kdbaux[9]; 267 f->f_regs[GP] = kdbaux[10]; 268 } 269 } 270 271 /* 272 * Read bytes from kernel address space for debugger. 273 */ 274 void 275 db_read_bytes(vaddr_t addr, size_t size, char *data) 276 { 277 278 while (size >= 4) 279 *((int*)data)++ = kdbpeek(addr), addr += 4, size -= 4; 280 while (size >= 2) 281 *((short*)data)++ = kdbpeek_2(addr), addr += 2, size -= 2; 282 if (size == 1) 283 *((char*)data)++ = kdbpeek_1(addr); 284 } 285 286 /* 287 * Write bytes to kernel address space for debugger. 288 */ 289 void 290 db_write_bytes(vaddr_t addr, size_t size, char *data) 291 { 292 vaddr_t p = addr; 293 size_t n = size; 294 295 #ifdef DEBUG_DDB 296 printf("db_write_bytes(%lx, %d, %p, val %x)\n", addr, size, data, 297 (addr &3 ) == 0? *(u_int*)addr: -1); 298 #endif 299 300 while (n >= 4) { 301 kdbpoke_4(p, *(int*)data); 302 p += 4; 303 data += 4; 304 n -= 4; 305 } 306 if (n >= 2) { 307 kdbpoke_2(p, *(short*)data); 308 p += 2; 309 data += 2; 310 n -= 2; 311 } 312 if (n == 1) { 313 kdbpoke_1(p, *(char*)data); 314 } 315 316 mips_icache_sync_range((vaddr_t) addr, size); 317 } 318 319 #ifndef KGDB 320 void 321 db_tlbdump_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) 322 { 323 324 #ifdef MIPS1 325 if (!MIPS_HAS_R4K_MMU) { 326 struct mips1_tlb { 327 u_int32_t tlb_hi; 328 u_int32_t tlb_lo; 329 } tlb; 330 int i; 331 void mips1_TLBRead(int, struct mips1_tlb *); 332 333 for (i = 0; i < mips_num_tlb_entries; i++) { 334 mips1_TLBRead(i, &tlb); 335 db_printf("TLB%c%2d Hi 0x%08x Lo 0x%08x", 336 (tlb.tlb_lo & MIPS1_PG_V) ? ' ' : '*', 337 i, tlb.tlb_hi, 338 tlb.tlb_lo & MIPS1_PG_FRAME); 339 db_printf(" %c%c%c\n", 340 (tlb.tlb_lo & MIPS1_PG_D) ? 'D' : ' ', 341 (tlb.tlb_lo & MIPS1_PG_G) ? 'G' : ' ', 342 (tlb.tlb_lo & MIPS1_PG_N) ? 'N' : ' '); 343 } 344 } 345 #endif 346 #ifdef MIPS3_PLUS 347 if (MIPS_HAS_R4K_MMU) { 348 struct tlb tlb; 349 int i; 350 351 for (i = 0; i < mips_num_tlb_entries; i++) { 352 #if defined(MIPS3) 353 #if defined(MIPS3_5900) 354 mips5900_TLBRead(i, &tlb); 355 #else 356 mips3_TLBRead(i, &tlb); 357 #endif 358 #elif defined(MIPS32) 359 mips32_TLBRead(i, &tlb); 360 #elif defined(MIPS64) 361 mips64_TLBRead(i, &tlb); 362 #endif 363 db_printf("TLB%c%2d Hi 0x%08x ", 364 (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*', 365 i, tlb.tlb_hi); 366 db_printf("Lo0=0x%08x %c%c attr %x ", 367 (unsigned)mips_tlbpfn_to_paddr(tlb.tlb_lo0), 368 (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ', 369 (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ', 370 (tlb.tlb_lo0 >> 3) & 7); 371 db_printf("Lo1=0x%08x %c%c attr %x sz=%x\n", 372 (unsigned)mips_tlbpfn_to_paddr(tlb.tlb_lo1), 373 (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ', 374 (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ', 375 (tlb.tlb_lo1 >> 3) & 7, 376 tlb.tlb_mask); 377 } 378 } 379 #endif 380 } 381 382 void 383 db_kvtophys_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) 384 { 385 386 if (!have_addr) 387 return; 388 if (MIPS_KSEG2_START <= addr) { 389 /* 390 * Cast the physical address -- some platforms, while 391 * being ILP32, may be using 64-bit paddr_t's. 392 */ 393 db_printf("0x%lx -> 0x%qx\n", addr, 394 (unsigned long long) kvtophys(addr)); 395 } else 396 printf("not a kernel virtual address\n"); 397 } 398 399 #define FLDWIDTH 10 400 #define SHOW32(reg, name) \ 401 do { \ 402 uint32_t __val; \ 403 \ 404 asm volatile("mfc0 %0,$" ___STRING(reg) : "=r"(__val)); \ 405 printf(" %s:%*s %#x\n", name, FLDWIDTH - strlen(name), "", __val); \ 406 } while (0) 407 408 /* XXX not 64-bit ABI safe! */ 409 #define SHOW64(reg, name) \ 410 do { \ 411 uint64_t __val; \ 412 \ 413 asm volatile( \ 414 ".set push \n\t" \ 415 ".set mips3 \n\t" \ 416 ".set noat \n\t" \ 417 "dmfc0 $1,$" ___STRING(reg) " \n\t" \ 418 "dsll %L0,$1,32 \n\t" \ 419 "dsrl %L0,%L0,32 \n\t" \ 420 "dsrl %M0,$1,32 \n\t" \ 421 ".set pop" \ 422 : "=r"(__val)); \ 423 printf(" %s:%*s %#llx\n", name, FLDWIDTH - strlen(name), "", __val); \ 424 } while (0) 425 426 void 427 db_cp0dump_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) 428 { 429 430 SHOW32(MIPS_COP_0_TLB_INDEX, "index"); 431 SHOW32(MIPS_COP_0_TLB_RANDOM, "random"); 432 433 if (!MIPS_HAS_R4K_MMU) { 434 SHOW32(MIPS_COP_0_TLB_LOW, "entrylow"); 435 } else { 436 if (CPUIS64BITS) { 437 SHOW64(MIPS_COP_0_TLB_LO0, "entrylo0"); 438 SHOW64(MIPS_COP_0_TLB_LO1, "entrylo1"); 439 } else { 440 SHOW32(MIPS_COP_0_TLB_LO0, "entrylo0"); 441 SHOW32(MIPS_COP_0_TLB_LO1, "entrylo1"); 442 } 443 } 444 445 if (CPUIS64BITS) { 446 SHOW64(MIPS_COP_0_TLB_CONTEXT, "context"); 447 } else { 448 SHOW32(MIPS_COP_0_TLB_CONTEXT, "context"); 449 } 450 451 if (MIPS_HAS_R4K_MMU) { 452 SHOW32(MIPS_COP_0_TLB_PG_MASK, "pagemask"); 453 SHOW32(MIPS_COP_0_TLB_WIRED, "wired"); 454 } 455 456 if (CPUIS64BITS) { 457 SHOW64(MIPS_COP_0_BAD_VADDR, "badvaddr"); 458 } else { 459 SHOW32(MIPS_COP_0_BAD_VADDR, "badvaddr"); 460 } 461 462 if (cpu_arch >= CPU_ARCH_MIPS3) { 463 SHOW32(MIPS_COP_0_COUNT, "count"); 464 } 465 466 if (CPUIS64BITS) { 467 SHOW64(MIPS_COP_0_TLB_HI, "entryhi"); 468 } else { 469 SHOW32(MIPS_COP_0_TLB_HI, "entryhi"); 470 } 471 472 if (cpu_arch >= CPU_ARCH_MIPS3) { 473 SHOW32(MIPS_COP_0_COMPARE, "compare"); 474 } 475 476 SHOW32(MIPS_COP_0_STATUS, "status"); 477 SHOW32(MIPS_COP_0_CAUSE, "cause"); 478 479 if (CPUIS64BITS) { 480 SHOW64(MIPS_COP_0_EXC_PC, "epc"); 481 } else { 482 SHOW32(MIPS_COP_0_EXC_PC, "epc"); 483 } 484 485 SHOW32(MIPS_COP_0_PRID, "prid"); 486 SHOW32(MIPS_COP_0_CONFIG, "config"); 487 488 #if defined(MIPS32) || defined(MIPS64) 489 if (CPUISMIPSNN) { 490 uint32_t val; 491 492 val = mipsNN_cp0_config1_read(); 493 printf(" config1: %#x\n", val); 494 } 495 #endif 496 497 if (MIPS_HAS_LLSC) { 498 if (CPUISMIPS64) { 499 SHOW64(MIPS_COP_0_LLADDR, "lladdr"); 500 SHOW64(MIPS_COP_0_WATCH_LO, "watchlo"); 501 } else { 502 SHOW32(MIPS_COP_0_LLADDR, "lladdr"); 503 SHOW32(MIPS_COP_0_WATCH_LO, "watchlo"); 504 } 505 506 SHOW32(MIPS_COP_0_WATCH_HI, "watchhi"); 507 508 if (CPUIS64BITS) { 509 SHOW64(MIPS_COP_0_TLB_XCONTEXT, "xcontext"); 510 } 511 512 if (CPUISMIPSNN) { 513 if (CPUISMIPS64) { 514 SHOW64(MIPS_COP_0_PERFCNT, "perfcnt"); 515 } else { 516 SHOW32(MIPS_COP_0_PERFCNT, "perfcnt"); 517 } 518 } 519 520 SHOW32(MIPS_COP_0_ECC, "ecc"); 521 SHOW32(MIPS_COP_0_CACHE_ERR, "cacherr"); 522 SHOW32(MIPS_COP_0_TAG_LO, "cachelo"); 523 SHOW32(MIPS_COP_0_TAG_HI, "cachehi"); 524 525 if (CPUIS64BITS) { 526 SHOW64(MIPS_COP_0_ERROR_PC, "errorpc"); 527 } else { 528 SHOW32(MIPS_COP_0_ERROR_PC, "errorpc"); 529 } 530 } 531 } 532 533 const struct db_command db_machine_command_table[] = { 534 { "kvtop", db_kvtophys_cmd, 0, 0 }, 535 { "tlb", db_tlbdump_cmd, 0, 0 }, 536 { "cp0", db_cp0dump_cmd, 0, 0 }, 537 { (char *)0, } 538 }; 539 #endif /* !KGDB */ 540 541 /* 542 * Determine whether the instruction involves a delay slot. 543 */ 544 boolean_t 545 inst_branch(int inst) 546 { 547 InstFmt i; 548 int delay; 549 550 i.word = inst; 551 delay = 0; 552 switch (i.JType.op) { 553 case OP_BCOND: 554 case OP_J: 555 case OP_JAL: 556 case OP_BEQ: 557 case OP_BNE: 558 case OP_BLEZ: 559 case OP_BGTZ: 560 case OP_BEQL: 561 case OP_BNEL: 562 case OP_BLEZL: 563 case OP_BGTZL: 564 delay = 1; 565 break; 566 567 case OP_COP0: 568 case OP_COP1: 569 switch (i.RType.rs) { 570 case OP_BCx: 571 case OP_BCy: 572 delay = 1; 573 } 574 break; 575 576 case OP_SPECIAL: 577 if (i.RType.op == OP_JR || i.RType.op == OP_JALR) 578 delay = 1; 579 break; 580 } 581 return delay; 582 } 583 584 /* 585 * Determine whether the instruction calls a function. 586 */ 587 boolean_t 588 inst_call(int inst) 589 { 590 boolean_t call; 591 InstFmt i; 592 593 i.word = inst; 594 if (i.JType.op == OP_SPECIAL 595 && ((i.RType.func == OP_JR && i.RType.rs != 31) || 596 i.RType.func == OP_JALR)) 597 call = 1; 598 else if (i.JType.op == OP_JAL) 599 call = 1; 600 else 601 call = 0; 602 return call; 603 } 604 605 /* 606 * Determine whether the instruction returns from a function (j ra). The 607 * compiler can use this construct for other jumps, but usually will not. 608 * This lets the ddb "next" command to work (also need inst_trap_return()). 609 */ 610 boolean_t 611 inst_return(int inst) 612 { 613 InstFmt i; 614 615 i.word = inst; 616 617 return (i.JType.op == OP_SPECIAL && i.RType.func == OP_JR && 618 i.RType.rs == 31); 619 } 620 621 /* 622 * Determine whether the instruction makes a jump. 623 */ 624 boolean_t 625 inst_unconditional_flow_transfer(int inst) 626 { 627 InstFmt i; 628 boolean_t jump; 629 630 i.word = inst; 631 jump = (i.JType.op == OP_J) || 632 (i.JType.op == OP_SPECIAL && i.RType.func == OP_JR); 633 return jump; 634 } 635 636 /* 637 * Determine whether the instruction is a load/store as appropriate. 638 */ 639 boolean_t 640 inst_load(int inst) 641 { 642 InstFmt i; 643 644 i.word = inst; 645 646 switch (i.JType.op) { 647 case OP_LWC1: 648 case OP_LB: 649 case OP_LH: 650 case OP_LW: 651 case OP_LD: 652 case OP_LBU: 653 case OP_LHU: 654 case OP_LWU: 655 case OP_LDL: 656 case OP_LDR: 657 case OP_LWL: 658 case OP_LWR: 659 case OP_LL: 660 return 1; 661 default: 662 return 0; 663 } 664 } 665 666 boolean_t 667 inst_store(int inst) 668 { 669 InstFmt i; 670 671 i.word = inst; 672 673 switch (i.JType.op) { 674 case OP_SWC1: 675 case OP_SB: 676 case OP_SH: 677 case OP_SW: 678 case OP_SD: 679 case OP_SDL: 680 case OP_SDR: 681 case OP_SWL: 682 case OP_SWR: 683 case OP_SCD: 684 return 1; 685 default: 686 return 0; 687 } 688 } 689 690 /* 691 * Return the next pc if the given branch is taken. 692 * MachEmulateBranch() runs analysis for branch delay slot. 693 */ 694 db_addr_t 695 branch_taken(int inst, db_addr_t pc, db_regs_t *regs) 696 { 697 vaddr_t ra; 698 unsigned fpucsr; 699 700 fpucsr = curproc ? PCB_FSR(&curproc->p_addr->u_pcb) : 0; 701 ra = MachEmulateBranch((struct frame *)regs, pc, fpucsr, 0); 702 return ra; 703 } 704 705 /* 706 * Return the next pc of an arbitrary instruction. 707 */ 708 db_addr_t 709 next_instr_address(db_addr_t pc, boolean_t bd) 710 { 711 unsigned ins; 712 713 if (bd == FALSE) 714 return (pc + 4); 715 716 if (pc < MIPS_KSEG0_START) 717 ins = fuiword((void *)pc); 718 else 719 ins = *(unsigned *)pc; 720 721 if (inst_branch(ins) || inst_call(ins) || inst_return(ins)) 722 return (pc + 4); 723 724 return (pc); 725 } 726