1/* armrdi.c -- ARMulator RDI interface: ARM6 Instruction Emulator. 2 Copyright (C) 1994 Advanced RISC Machines Ltd. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program; if not, write to the Free Software 16 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 17 18#include <string.h> 19#include <ctype.h> 20#include "armdefs.h" 21#include "armemu.h" 22#include "armos.h" 23#include "dbg_cp.h" 24#include "dbg_conf.h" 25#include "dbg_rdi.h" 26#include "dbg_hif.h" 27#include "communicate.h" 28 29/***************************************************************************\ 30* Declarations * 31\***************************************************************************/ 32 33#define Watch_AnyRead (RDIWatch_ByteRead+RDIWatch_HalfRead+RDIWatch_WordRead) 34#define Watch_AnyWrite (RDIWatch_ByteWrite+RDIWatch_HalfWrite+RDIWatch_WordWrite) 35 36static unsigned FPRegsAddr; /* last known address of FPE regs */ 37#define FPESTART 0x2000L 38#define FPEEND 0x8000L 39 40#define IGNORE(d) (d = d) 41#ifdef RDI_VERBOSE 42#define TracePrint(s) \ 43 if (rdi_log & 1) ARMul_DebugPrint s 44#else 45#define TracePrint(s) 46#endif 47 48static ARMul_State *state = NULL; 49static unsigned BreaksSet; /* The number of breakpoints set */ 50 51static int rdi_log = 0; /* debugging ? */ 52 53#define LOWEST_RDI_LEVEL 0 54#define HIGHEST_RDI_LEVEL 1 55static int MYrdi_level = LOWEST_RDI_LEVEL; 56 57typedef struct BreakNode BreakNode; 58typedef struct WatchNode WatchNode; 59 60struct BreakNode 61{ /* A breakpoint list node */ 62 BreakNode *next; 63 ARMword address; /* The address of this breakpoint */ 64 unsigned type; /* The type of comparison */ 65 ARMword bound; /* The other address for a range */ 66 ARMword inst; 67}; 68 69struct WatchNode 70{ /* A watchpoint list node */ 71 WatchNode *next; 72 ARMword address; /* The address of this watchpoint */ 73 unsigned type; /* The type of comparison */ 74 unsigned datatype; /* The type of access to watch for */ 75 ARMword bound; /* The other address for a range */ 76}; 77 78BreakNode *BreakList = NULL; 79WatchNode *WatchList = NULL; 80 81void 82ARMul_DebugPrint_i (const Dbg_HostosInterface * hostif, const char *format, 83 ...) 84{ 85 va_list ap; 86 va_start (ap, format); 87 hostif->dbgprint (hostif->dbgarg, format, ap); 88 va_end (ap); 89} 90 91void 92ARMul_DebugPrint (ARMul_State * state, const char *format, ...) 93{ 94 va_list ap; 95 va_start (ap, format); 96 if (!(rdi_log & 8)) 97 state->hostif->dbgprint (state->hostif->dbgarg, format, ap); 98 va_end (ap); 99} 100 101#define CONSOLE_PRINT_MAX_LEN 128 102 103void 104ARMul_ConsolePrint (ARMul_State * state, const char *format, ...) 105{ 106 va_list ap; 107 int ch; 108 char *str, buf[CONSOLE_PRINT_MAX_LEN]; 109 int i, j; 110 ARMword junk; 111 112 va_start (ap, format); 113 vsprintf (buf, format, ap); 114 115 for (i = 0; buf[i]; i++); /* The string is i chars long */ 116 117 str = buf; 118 while (i >= 32) 119 { 120 MYwrite_char (kidmum[1], RDP_OSOp); 121 MYwrite_word (kidmum[1], SWI_Write0); 122 MYwrite_char (kidmum[1], OS_SendString); 123 MYwrite_char (kidmum[1], 32); /* Send string 32bytes at a time */ 124 for (j = 0; j < 32; j++, str++) 125 MYwrite_char (kidmum[1], *str); 126 wait_for_osreply (&junk); 127 i -= 32; 128 } 129 130 if (i > 0) 131 { 132 MYwrite_char (kidmum[1], RDP_OSOp); 133 MYwrite_word (kidmum[1], SWI_Write0); 134 MYwrite_char (kidmum[1], OS_SendString); 135 MYwrite_char (kidmum[1], (unsigned char) i); /* Send remainder of string */ 136 for (j = 0; j < i; j++, str++) 137 MYwrite_char (kidmum[1], *str); 138 wait_for_osreply (&junk); 139 } 140 141 va_end (ap); 142 return; 143 144/* str = buf; */ 145/* while ((ch=*str++) != 0) */ 146/* state->hostif->writec(state->hostif->hostosarg, ch); */ 147} 148 149void 150ARMul_DebugPause (ARMul_State * state) 151{ 152 if (!(rdi_log & 8)) 153 state->hostif->dbgpause (state->hostif->dbgarg); 154} 155 156/***************************************************************************\ 157* RDI_open * 158\***************************************************************************/ 159 160static void 161InitFail (int exitcode, char const *which) 162{ 163 ARMul_ConsolePrint (state, "%s interface failed to initialise. Exiting\n", 164 which); 165 exit (exitcode); 166} 167 168static void 169RDIInit (unsigned type) 170{ 171 if (type == 0) 172 { /* cold start */ 173 state->CallDebug = state->MemReadDebug = state->MemWriteDebug = 0; 174 BreaksSet = 0; 175 } 176} 177 178#define UNKNOWNPROC 0 179 180typedef struct 181{ 182 char name[16]; 183 unsigned properties; 184} 185Processor; 186 187Processor const p_arm2 = { "ARM2", ARM_Fix26_Prop }; 188Processor const p_arm2as = { "ARM2AS", ARM_Fix26_Prop }; 189Processor const p_arm61 = { "ARM61", ARM_Fix26_Prop }; 190Processor const p_arm3 = { "ARM3", ARM_Fix26_Prop }; 191Processor const p_arm6 = { "ARM6", ARM_Lock_Prop }; 192Processor const p_arm60 = { "ARM60", ARM_Lock_Prop }; 193Processor const p_arm600 = { "ARM600", ARM_Lock_Prop }; 194Processor const p_arm610 = { "ARM610", ARM_Lock_Prop }; 195Processor const p_arm620 = { "ARM620", ARM_Lock_Prop }; 196Processor const p_unknown = { "", 0 }; 197 198Processor const *const processors[] = 199{ 200 &p_arm6, /* default: must come first */ 201 &p_arm2, 202 &p_arm2as, 203 &p_arm61, 204 &p_arm3, 205 &p_arm60, 206 &p_arm600, 207 &p_arm610, 208 &p_arm620, 209 &p_unknown 210}; 211 212typedef struct ProcessorConfig ProcessorConfig; 213struct ProcessorConfig 214{ 215 long id[2]; 216 ProcessorConfig const *self; 217 long count; 218 Processor const *const *processors; 219}; 220 221ProcessorConfig const processorconfig = { 222 {((((((long) 'x' << 8) | ' ') << 8) | 'c') << 8) | 'p', 223 ((((((long) 'u' << 8) | 's') << 8) | ' ') << 8) | 'x'}, 224 &processorconfig, 225 16, 226 processors 227}; 228 229static int 230RDI_open (unsigned type, const Dbg_ConfigBlock * config, 231 const Dbg_HostosInterface * hostif, struct Dbg_MCState *dbg_state) 232/* Initialise everything */ 233{ 234 int virgin = (state == NULL); 235 IGNORE (dbg_state); 236 237#ifdef RDI_VERBOSE 238 if (rdi_log & 1) 239 { 240 if (virgin) 241 ARMul_DebugPrint_i (hostif, "RDI_open: type = %d\n", type); 242 else 243 ARMul_DebugPrint (state, "RDI_open: type = %d\n", type); 244 } 245#endif 246 247 if (type & 1) 248 { /* Warm start */ 249 ARMul_Reset (state); 250 RDIInit (1); 251 } 252 else 253 { 254 if (virgin) 255 { 256 ARMul_EmulateInit (); 257 state = ARMul_NewState (); 258 state->hostif = hostif; 259 { 260 int req = config->processor; 261 unsigned processor = processors[req]->val; 262 ARMul_SelectProcessor (state, processor); 263 ARMul_Reset (state); 264 ARMul_ConsolePrint (state, "ARMulator V1.50, %s", 265 processors[req]->name); 266 } 267 if (ARMul_MemoryInit (state, config->memorysize) == FALSE) 268 InitFail (1, "Memory"); 269 if (config->bytesex != RDISex_DontCare) 270 state->bigendSig = config->bytesex; 271 if (ARMul_CoProInit (state) == FALSE) 272 InitFail (2, "Co-Processor"); 273 if (ARMul_OSInit (state) == FALSE) 274 InitFail (3, "Operating System"); 275 } 276 ARMul_Reset (state); 277 RDIInit (0); 278 } 279 if (type & 2) 280 { /* Reset the comms link */ 281 /* what comms link ? */ 282 } 283 if (virgin && (type & 1) == 0) /* Cold start */ 284 ARMul_ConsolePrint (state, ", %s endian.\n", 285 state->bigendSig ? "Big" : "Little"); 286 287 if (config->bytesex == RDISex_DontCare) 288 return (state->bigendSig ? RDIError_BigEndian : RDIError_LittleEndian); 289 else 290 return (RDIError_NoError); 291} 292 293/***************************************************************************\ 294* RDI_close * 295\***************************************************************************/ 296 297static int 298RDI_close (void) 299{ 300 TracePrint ((state, "RDI_close\n")); 301 ARMul_OSExit (state); 302 ARMul_CoProExit (state); 303 ARMul_MemoryExit (state); 304 return (RDIError_NoError); 305} 306 307/***************************************************************************\ 308* RDI_read * 309\***************************************************************************/ 310 311static int 312RDI_read (ARMword source, void *dest, unsigned *nbytes) 313{ 314 unsigned i; 315 char *memptr = (char *) dest; 316 317 TracePrint ((state, "RDI_read: source=%.8lx dest=%p nbytes=%.8x\n", 318 source, dest, *nbytes)); 319 320 for (i = 0; i < *nbytes; i++) 321 *memptr++ = (char) ARMul_ReadByte (state, source++); 322 if (state->abortSig) 323 { 324 state->abortSig = LOW; 325 return (RDIError_DataAbort); 326 } 327 return (RDIError_NoError); 328} 329 330/***************************************************************************\ 331* RDI_write * 332\***************************************************************************/ 333 334static int 335RDI_write (const void *source, ARMword dest, unsigned *nbytes) 336{ 337 unsigned i; 338 char *memptr = (char *) source; 339 340 TracePrint ((state, "RDI_write: source=%p dest=%.8lx nbytes=%.8x\n", 341 source, dest, *nbytes)); 342 343 for (i = 0; i < *nbytes; i++) 344 ARMul_WriteByte (state, (ARMword) dest++, (ARMword) * memptr++); 345 346 if (state->abortSig) 347 { 348 state->abortSig = LOW; 349 return (RDIError_DataAbort); 350 } 351 return (RDIError_NoError); 352} 353 354/***************************************************************************\ 355* RDI_CPUread * 356\***************************************************************************/ 357 358static int 359RDI_CPUread (unsigned mode, unsigned long mask, ARMword buffer[]) 360{ 361 unsigned i, upto; 362 363 if (mode == RDIMode_Curr) 364 mode = (unsigned) (ARMul_GetCPSR (state) & MODEBITS); 365 366 for (upto = 0, i = 0; i < 15; i++) 367 if (mask & (1L << i)) 368 { 369 buffer[upto++] = ARMul_GetReg (state, mode, i); 370 } 371 372 if (mask & RDIReg_R15) 373 { 374 buffer[upto++] = ARMul_GetR15 (state); 375 } 376 377 if (mask & RDIReg_PC) 378 { 379 buffer[upto++] = ARMul_GetPC (state); 380 } 381 382 if (mask & RDIReg_CPSR) 383 buffer[upto++] = ARMul_GetCPSR (state); 384 385 if (mask & RDIReg_SPSR) 386 buffer[upto++] = ARMul_GetSPSR (state, mode); 387 388 TracePrint ((state, "RDI_CPUread: mode=%.8x mask=%.8lx", mode, mask)); 389#ifdef RDI_VERBOSE 390 if (rdi_log & 1) 391 { 392 for (upto = 0, i = 0; i <= 20; i++) 393 if (mask & (1L << i)) 394 { 395 ARMul_DebugPrint (state, "%c%.8lx", upto % 4 == 0 ? '\n' : ' ', 396 buffer[upto]); 397 upto++; 398 } 399 ARMul_DebugPrint (state, "\n"); 400 } 401#endif 402 403 return (RDIError_NoError); 404} 405 406/***************************************************************************\ 407* RDI_CPUwrite * 408\***************************************************************************/ 409 410static int 411RDI_CPUwrite (unsigned mode, unsigned long mask, ARMword const buffer[]) 412{ 413 int i, upto; 414 415 416 TracePrint ((state, "RDI_CPUwrite: mode=%.8x mask=%.8lx", mode, mask)); 417#ifdef RDI_VERBOSE 418 if (rdi_log & 1) 419 { 420 for (upto = 0, i = 0; i <= 20; i++) 421 if (mask & (1L << i)) 422 { 423 ARMul_DebugPrint (state, "%c%.8lx", upto % 4 == 0 ? '\n' : ' ', 424 buffer[upto]); 425 upto++; 426 } 427 ARMul_DebugPrint (state, "\n"); 428 } 429#endif 430 431 if (mode == RDIMode_Curr) 432 mode = (unsigned) (ARMul_GetCPSR (state) & MODEBITS); 433 434 for (upto = 0, i = 0; i < 15; i++) 435 if (mask & (1L << i)) 436 ARMul_SetReg (state, mode, i, buffer[upto++]); 437 438 if (mask & RDIReg_R15) 439 ARMul_SetR15 (state, buffer[upto++]); 440 441 if (mask & RDIReg_PC) 442 { 443 444 ARMul_SetPC (state, buffer[upto++]); 445 } 446 if (mask & RDIReg_CPSR) 447 ARMul_SetCPSR (state, buffer[upto++]); 448 449 if (mask & RDIReg_SPSR) 450 ARMul_SetSPSR (state, mode, buffer[upto++]); 451 452 return (RDIError_NoError); 453} 454 455/***************************************************************************\ 456* RDI_CPread * 457\***************************************************************************/ 458 459static int 460RDI_CPread (unsigned CPnum, unsigned long mask, ARMword buffer[]) 461{ 462 ARMword fpregsaddr, word[4]; 463 464 unsigned r, w; 465 unsigned upto; 466 467 if (CPnum != 1 && CPnum != 2) 468 { 469 unsigned char const *rmap = state->CPRegWords[CPnum]; 470 if (rmap == NULL) 471 return (RDIError_UnknownCoPro); 472 for (upto = 0, r = 0; r < rmap[-1]; r++) 473 if (mask & (1L << r)) 474 { 475 (void) state->CPRead[CPnum] (state, r, &buffer[upto]); 476 upto += rmap[r]; 477 } 478 TracePrint ((state, "RDI_CPread: CPnum=%d mask=%.8lx", CPnum, mask)); 479#ifdef RDI_VERBOSE 480 if (rdi_log & 1) 481 { 482 w = 0; 483 for (upto = 0, r = 0; r < rmap[-1]; r++) 484 if (mask & (1L << r)) 485 { 486 int words = rmap[r]; 487 ARMul_DebugPrint (state, "%c%2d", 488 (w >= 4 ? (w = 0, '\n') : ' '), r); 489 while (--words >= 0) 490 { 491 ARMul_DebugPrint (state, " %.8lx", buffer[upto++]); 492 w++; 493 } 494 } 495 ARMul_DebugPrint (state, "\n"); 496 } 497#endif 498 return RDIError_NoError; 499 } 500 501#ifdef NOFPE 502 return RDIError_UnknownCoPro; 503 504#else 505 if (FPRegsAddr == 0) 506 { 507 fpregsaddr = ARMul_ReadWord (state, 4L); 508 if ((fpregsaddr & 0xff800000) != 0xea000000) /* Must be a forward branch */ 509 return RDIError_UnknownCoPro; 510 fpregsaddr = ((fpregsaddr & 0xffffff) << 2) + 8; /* address in __fp_decode - 4 */ 511 if ((fpregsaddr < FPESTART) || (fpregsaddr >= FPEEND)) 512 return RDIError_UnknownCoPro; 513 fpregsaddr = ARMul_ReadWord (state, fpregsaddr); /* pointer to fp registers */ 514 FPRegsAddr = fpregsaddr; 515 } 516 else 517 fpregsaddr = FPRegsAddr; 518 519 if (fpregsaddr == 0) 520 return RDIError_UnknownCoPro; 521 for (upto = 0, r = 0; r < 8; r++) 522 if (mask & (1L << r)) 523 { 524 for (w = 0; w < 4; w++) 525 word[w] = 526 ARMul_ReadWord (state, 527 fpregsaddr + (ARMword) r * 16 + (ARMword) w * 4); 528 switch ((int) (word[3] >> 29)) 529 { 530 case 0: 531 case 2: 532 case 4: 533 case 6: /* its unpacked, convert to extended */ 534 buffer[upto++] = 2; /* mark as extended */ 535 buffer[upto++] = (word[3] & 0x7fff) | (word[0] & 0x80000000); /* exp and sign */ 536 buffer[upto++] = word[1]; /* mantissa 1 */ 537 buffer[upto++] = word[2]; /* mantissa 2 */ 538 break; 539 case 1: /* packed single */ 540 buffer[upto++] = 0; /* mark as single */ 541 buffer[upto++] = word[0]; /* sign, exp and mantissa */ 542 buffer[upto++] = word[1]; /* padding */ 543 buffer[upto++] = word[2]; /* padding */ 544 break; 545 case 3: /* packed double */ 546 buffer[upto++] = 1; /* mark as double */ 547 buffer[upto++] = word[0]; /* sign, exp and mantissa1 */ 548 buffer[upto++] = word[1]; /* mantissa 2 */ 549 buffer[upto++] = word[2]; /* padding */ 550 break; 551 case 5: /* packed extended */ 552 buffer[upto++] = 2; /* mark as extended */ 553 buffer[upto++] = word[0]; /* sign and exp */ 554 buffer[upto++] = word[1]; /* mantissa 1 */ 555 buffer[upto++] = word[2]; /* mantissa 2 */ 556 break; 557 case 7: /* packed decimal */ 558 buffer[upto++] = 3; /* mark as packed decimal */ 559 buffer[upto++] = word[0]; /* sign, exp and mantissa1 */ 560 buffer[upto++] = word[1]; /* mantissa 2 */ 561 buffer[upto++] = word[2]; /* mantissa 3 */ 562 break; 563 } 564 } 565 if (mask & (1L << r)) 566 buffer[upto++] = ARMul_ReadWord (state, fpregsaddr + 128); /* fpsr */ 567 if (mask & (1L << (r + 1))) 568 buffer[upto++] = 0; /* fpcr */ 569 570 TracePrint ((state, "RDI_CPread: CPnum=%d mask=%.8lx\n", CPnum, mask)); 571#ifdef RDI_VERBOSE 572 if (rdi_log & 1) 573 { 574 for (upto = 0, r = 0; r < 9; r++) 575 if (mask & (1L << r)) 576 { 577 if (r != 8) 578 { 579 ARMul_DebugPrint (state, "%08lx ", buffer[upto++]); 580 ARMul_DebugPrint (state, "%08lx ", buffer[upto++]); 581 ARMul_DebugPrint (state, "%08lx ", buffer[upto++]); 582 } 583 ARMul_DebugPrint (state, "%08lx\n", buffer[upto++]); 584 } 585 ARMul_DebugPrint (state, "\n"); 586 } 587#endif 588 return (RDIError_NoError); 589#endif /* NOFPE */ 590} 591 592/***************************************************************************\ 593* RDI_CPwrite * 594\***************************************************************************/ 595 596static int 597RDI_CPwrite (unsigned CPnum, unsigned long mask, ARMword const buffer[]) 598{ 599 unsigned r; 600 unsigned upto; 601 ARMword fpregsaddr; 602 603 if (CPnum != 1 && CPnum != 2) 604 { 605 unsigned char const *rmap = state->CPRegWords[CPnum]; 606 if (rmap == NULL) 607 return (RDIError_UnknownCoPro); 608 TracePrint ((state, "RDI_CPwrite: CPnum=%d mask=%.8lx", CPnum, mask)); 609#ifdef RDI_VERBOSE 610 if (rdi_log & 1) 611 { 612 int w = 0; 613 for (upto = 0, r = 0; r < rmap[-1]; r++) 614 if (mask & (1L << r)) 615 { 616 int words = rmap[r]; 617 ARMul_DebugPrint (state, "%c%2d", 618 (w >= 4 ? (w = 0, '\n') : ' '), r); 619 while (--words >= 0) 620 { 621 ARMul_DebugPrint (state, " %.8lx", buffer[upto++]); 622 w++; 623 } 624 } 625 ARMul_DebugPrint (state, "\n"); 626 } 627#endif 628 for (upto = 0, r = 0; r < rmap[-1]; r++) 629 if (mask & (1L << r)) 630 { 631 (void) state->CPWrite[CPnum] (state, r, &buffer[upto]); 632 upto += rmap[r]; 633 } 634 return RDIError_NoError; 635 } 636 637#ifdef NOFPE 638 return RDIError_UnknownCoPro; 639 640#else 641 TracePrint ((state, "RDI_CPwrite: CPnum=%d mask=%.8lx", CPnum, mask)); 642#ifdef RDI_VERBOSE 643 if (rdi_log & 1) 644 { 645 for (upto = 0, r = 0; r < 9; r++) 646 if (mask & (1L << r)) 647 { 648 if (r != 8) 649 { 650 ARMul_DebugPrint (state, "%08lx ", buffer[upto++]); 651 ARMul_DebugPrint (state, "%08lx ", buffer[upto++]); 652 ARMul_DebugPrint (state, "%08lx ", buffer[upto++]); 653 } 654 ARMul_DebugPrint (state, "%08lx\n", buffer[upto++]); 655 } 656 ARMul_DebugPrint (state, "\n"); 657 } 658#endif 659 660 if (FPRegsAddr == 0) 661 { 662 fpregsaddr = ARMul_ReadWord (state, 4L); 663 if ((fpregsaddr & 0xff800000) != 0xea000000) /* Must be a forward branch */ 664 return RDIError_UnknownCoPro; 665 fpregsaddr = ((fpregsaddr & 0xffffff) << 2) + 8; /* address in __fp_decode - 4 */ 666 if ((fpregsaddr < FPESTART) || (fpregsaddr >= FPEEND)) 667 return RDIError_UnknownCoPro; 668 fpregsaddr = ARMul_ReadWord (state, fpregsaddr); /* pointer to fp registers */ 669 FPRegsAddr = fpregsaddr; 670 } 671 else 672 fpregsaddr = FPRegsAddr; 673 674 if (fpregsaddr == 0) 675 return RDIError_UnknownCoPro; 676 for (upto = 0, r = 0; r < 8; r++) 677 if (mask & (1L << r)) 678 { 679 ARMul_WriteWord (state, fpregsaddr + (ARMword) r * 16, 680 buffer[upto + 1]); 681 ARMul_WriteWord (state, fpregsaddr + (ARMword) r * 16 + 4, 682 buffer[upto + 2]); 683 ARMul_WriteWord (state, fpregsaddr + (ARMword) r * 16 + 8, 684 buffer[upto + 3]); 685 ARMul_WriteWord (state, fpregsaddr + (ARMword) r * 16 + 12, 686 (buffer[upto] * 2 + 1) << 29); /* mark type */ 687 upto += 4; 688 } 689 if (mask & (1L << r)) 690 ARMul_WriteWord (state, fpregsaddr + 128, buffer[upto++]); /* fpsr */ 691 return (RDIError_NoError); 692#endif /* NOFPE */ 693} 694 695static void 696deletebreaknode (BreakNode ** prevp) 697{ 698 BreakNode *p = *prevp; 699 *prevp = p->next; 700 ARMul_WriteWord (state, p->address, p->inst); 701 free ((char *) p); 702 BreaksSet--; 703 state->CallDebug--; 704} 705 706static int 707removebreak (ARMword address, unsigned type) 708{ 709 BreakNode *p, **prevp = &BreakList; 710 for (; (p = *prevp) != NULL; prevp = &p->next) 711 if (p->address == address && p->type == type) 712 { 713 deletebreaknode (prevp); 714 return TRUE; 715 } 716 return FALSE; 717} 718 719/* This routine installs a breakpoint into the breakpoint table */ 720 721static BreakNode * 722installbreak (ARMword address, unsigned type, ARMword bound) 723{ 724 BreakNode *p = (BreakNode *) malloc (sizeof (BreakNode)); 725 p->next = BreakList; 726 BreakList = p; 727 p->address = address; 728 p->type = type; 729 p->bound = bound; 730 p->inst = ARMul_ReadWord (state, address); 731 ARMul_WriteWord (state, address, 0xee000000L); 732 return p; 733} 734 735/***************************************************************************\ 736* RDI_setbreak * 737\***************************************************************************/ 738 739static int 740RDI_setbreak (ARMword address, unsigned type, ARMword bound, 741 PointHandle * handle) 742{ 743 BreakNode *p; 744 TracePrint ((state, "RDI_setbreak: address=%.8lx type=%d bound=%.8lx\n", 745 address, type, bound)); 746 747 removebreak (address, type); 748 p = installbreak (address, type, bound); 749 BreaksSet++; 750 state->CallDebug++; 751 *handle = (PointHandle) p; 752 TracePrint ((state, " returns %.8lx\n", *handle)); 753 return RDIError_NoError; 754} 755 756/***************************************************************************\ 757* RDI_clearbreak * 758\***************************************************************************/ 759 760static int 761RDI_clearbreak (PointHandle handle) 762{ 763 TracePrint ((state, "RDI_clearbreak: address=%.8lx\n", handle)); 764 { 765 BreakNode *p, **prevp = &BreakList; 766 for (; (p = *prevp) != NULL; prevp = &p->next) 767 if (p == (BreakNode *) handle) 768 break; 769 if (p == NULL) 770 return RDIError_NoSuchPoint; 771 deletebreaknode (prevp); 772 return RDIError_NoError; 773 } 774} 775 776/***************************************************************************\ 777* Internal functions for breakpoint table manipulation * 778\***************************************************************************/ 779 780static void 781deletewatchnode (WatchNode ** prevp) 782{ 783 WatchNode *p = *prevp; 784 if (p->datatype & Watch_AnyRead) 785 state->MemReadDebug--; 786 if (p->datatype & Watch_AnyWrite) 787 state->MemWriteDebug--; 788 *prevp = p->next; 789 free ((char *) p); 790} 791 792int 793removewatch (ARMword address, unsigned type) 794{ 795 WatchNode *p, **prevp = &WatchList; 796 for (; (p = *prevp) != NULL; prevp = &p->next) 797 if (p->address == address && p->type == type) 798 { /* found a match */ 799 deletewatchnode (prevp); 800 return TRUE; 801 } 802 return FALSE; /* never found a match */ 803} 804 805static WatchNode * 806installwatch (ARMword address, unsigned type, unsigned datatype, 807 ARMword bound) 808{ 809 WatchNode *p = (WatchNode *) malloc (sizeof (WatchNode)); 810 p->next = WatchList; 811 WatchList = p; 812 p->address = address; 813 p->type = type; 814 p->datatype = datatype; 815 p->bound = bound; 816 return p; 817} 818 819/***************************************************************************\ 820* RDI_setwatch * 821\***************************************************************************/ 822 823static int 824RDI_setwatch (ARMword address, unsigned type, unsigned datatype, 825 ARMword bound, PointHandle * handle) 826{ 827 WatchNode *p; 828 TracePrint ( 829 (state, 830 "RDI_setwatch: address=%.8lx type=%d datatype=%d bound=%.8lx", 831 address, type, datatype, bound)); 832 833 if (!state->CanWatch) 834 return RDIError_UnimplementedMessage; 835 836 removewatch (address, type); 837 p = installwatch (address, type, datatype, bound); 838 if (datatype & Watch_AnyRead) 839 state->MemReadDebug++; 840 if (datatype & Watch_AnyWrite) 841 state->MemWriteDebug++; 842 *handle = (PointHandle) p; 843 TracePrint ((state, " returns %.8lx\n", *handle)); 844 return RDIError_NoError; 845} 846 847/***************************************************************************\ 848* RDI_clearwatch * 849\***************************************************************************/ 850 851static int 852RDI_clearwatch (PointHandle handle) 853{ 854 TracePrint ((state, "RDI_clearwatch: address=%.8lx\n", handle)); 855 { 856 WatchNode *p, **prevp = &WatchList; 857 for (; (p = *prevp) != NULL; prevp = &p->next) 858 if (p == (WatchNode *) handle) 859 break; 860 if (p == NULL) 861 return RDIError_NoSuchPoint; 862 deletewatchnode (prevp); 863 return RDIError_NoError; 864 } 865} 866 867/***************************************************************************\ 868* RDI_execute * 869\***************************************************************************/ 870 871static int 872RDI_execute (PointHandle * handle) 873{ 874 TracePrint ((state, "RDI_execute\n")); 875 if (rdi_log & 4) 876 { 877 state->CallDebug++; 878 state->Debug = TRUE; 879 } 880 state->EndCondition = RDIError_NoError; 881 state->StopHandle = 0; 882 883 ARMul_DoProg (state); 884 885 *handle = state->StopHandle; 886 state->Reg[15] -= 8; /* undo the pipeline */ 887 if (rdi_log & 4) 888 { 889 state->CallDebug--; 890 state->Debug = FALSE; 891 } 892 return (state->EndCondition); 893} 894 895/***************************************************************************\ 896* RDI_step * 897\***************************************************************************/ 898 899static int 900RDI_step (unsigned ninstr, PointHandle * handle) 901{ 902 903 TracePrint ((state, "RDI_step\n")); 904 if (ninstr != 1) 905 return RDIError_UnimplementedMessage; 906 if (rdi_log & 4) 907 { 908 state->CallDebug++; 909 state->Debug = TRUE; 910 } 911 state->EndCondition = RDIError_NoError; 912 state->StopHandle = 0; 913 ARMul_DoInstr (state); 914 *handle = state->StopHandle; 915 state->Reg[15] -= 8; /* undo the pipeline */ 916 if (rdi_log & 4) 917 { 918 state->CallDebug--; 919 state->Debug = FALSE; 920 } 921 return (state->EndCondition); 922} 923 924/***************************************************************************\ 925* RDI_info * 926\***************************************************************************/ 927 928static int 929RDI_info (unsigned type, ARMword * arg1, ARMword * arg2) 930{ 931 switch (type) 932 { 933 case RDIInfo_Target: 934 TracePrint ((state, "RDI_Info_Target\n")); 935 /* Emulator, speed 10**5 IPS */ 936 *arg1 = 5 | HIGHEST_RDI_LEVEL << 5 | LOWEST_RDI_LEVEL << 8; 937 *arg2 = 1298224434; 938 return RDIError_NoError; 939 940 case RDIInfo_Points: 941 { 942 ARMword n = RDIPointCapability_Comparison | RDIPointCapability_Range | 943 RDIPointCapability_Mask | RDIPointCapability_Status; 944 TracePrint ((state, "RDI_Info_Points\n")); 945 if (state->CanWatch) 946 n |= (Watch_AnyRead + Watch_AnyWrite) << 2; 947 *arg1 = n; 948 return RDIError_NoError; 949 } 950 951 case RDIInfo_Step: 952 TracePrint ((state, "RDI_Info_Step\n")); 953 *arg1 = RDIStep_Single; 954 return RDIError_NoError; 955 956 case RDIInfo_MMU: 957 TracePrint ((state, "RDI_Info_MMU\n")); 958 *arg1 = 1313820229; 959 return RDIError_NoError; 960 961 case RDISignal_Stop: 962 TracePrint ((state, "RDISignal_Stop\n")); 963 state->CallDebug++; 964 state->EndCondition = RDIError_UserInterrupt; 965 return RDIError_NoError; 966 967 case RDIVector_Catch: 968 TracePrint ((state, "RDIVector_Catch %.8lx\n", *arg1)); 969 state->VectorCatch = (unsigned) *arg1; 970 return RDIError_NoError; 971 972 case RDISet_Cmdline: 973 TracePrint ((state, "RDI_Set_Cmdline %s\n", (char *) arg1)); 974 state->CommandLine = 975 (char *) malloc ((unsigned) strlen ((char *) arg1) + 1); 976 (void) strcpy (state->CommandLine, (char *) arg1); 977 return RDIError_NoError; 978 979 case RDICycles: 980 TracePrint ((state, "RDI_Info_Cycles\n")); 981 arg1[0] = 0; 982 arg1[1] = state->NumInstrs; 983 arg1[2] = 0; 984 arg1[3] = state->NumScycles; 985 arg1[4] = 0; 986 arg1[5] = state->NumNcycles; 987 arg1[6] = 0; 988 arg1[7] = state->NumIcycles; 989 arg1[8] = 0; 990 arg1[9] = state->NumCcycles; 991 arg1[10] = 0; 992 arg1[11] = state->NumFcycles; 993 return RDIError_NoError; 994 995 case RDIErrorP: 996 *arg1 = ARMul_OSLastErrorP (state); 997 TracePrint ((state, "RDI_ErrorP returns %ld\n", *arg1)); 998 return RDIError_NoError; 999 1000 case RDIInfo_DescribeCoPro: 1001 { 1002 int cpnum = *(int *) arg1; 1003 struct Dbg_CoProDesc *cpd = (struct Dbg_CoProDesc *) arg2; 1004 int i; 1005 unsigned char const *map = state->CPRegWords[cpnum]; 1006 if (map == NULL) 1007 return RDIError_UnknownCoPro; 1008 for (i = 0; i < cpd->entries; i++) 1009 { 1010 unsigned r, w = cpd->regdesc[i].nbytes / sizeof (ARMword); 1011 for (r = cpd->regdesc[i].rmin; r <= cpd->regdesc[i].rmax; r++) 1012 if (map[r] != w) 1013 return RDIError_BadCoProState; 1014 } 1015 return RDIError_NoError; 1016 } 1017 1018 case RDIInfo_RequestCoProDesc: 1019 { 1020 int cpnum = *(int *) arg1; 1021 struct Dbg_CoProDesc *cpd = (struct Dbg_CoProDesc *) arg2; 1022 int i = -1, lastw = -1, r; 1023 unsigned char const *map; 1024 if ((unsigned) cpnum >= 16) 1025 return RDIError_UnknownCoPro; 1026 map = state->CPRegWords[cpnum]; 1027 if (map == NULL) 1028 return RDIError_UnknownCoPro; 1029 for (r = 0; r < map[-1]; r++) 1030 { 1031 int words = map[r]; 1032 if (words == lastw) 1033 cpd->regdesc[i].rmax = r; 1034 else 1035 { 1036 if (++i >= cpd->entries) 1037 return RDIError_BufferFull; 1038 cpd->regdesc[i].rmax = cpd->regdesc[i].rmin = r; 1039 cpd->regdesc[i].nbytes = words * sizeof (ARMword); 1040 cpd->regdesc[i].access = 1041 Dbg_Access_Readable + Dbg_Access_Writable; 1042 } 1043 } 1044 cpd->entries = i + 1; 1045 return RDIError_NoError; 1046 } 1047 1048 case RDIInfo_Log: 1049 *arg1 = (ARMword) rdi_log; 1050 return RDIError_NoError; 1051 1052 case RDIInfo_SetLog: 1053 rdi_log = (int) *arg1; 1054 return RDIError_NoError; 1055 1056 case RDIInfo_CoPro: 1057 return RDIError_NoError; 1058 1059 case RDIPointStatus_Watch: 1060 { 1061 WatchNode *p, *handle = (WatchNode *) * arg1; 1062 for (p = WatchList; p != NULL; p = p->next) 1063 if (p == handle) 1064 { 1065 *arg1 = -1; 1066 *arg2 = 1; 1067 return RDIError_NoError; 1068 } 1069 return RDIError_NoSuchPoint; 1070 } 1071 1072 case RDIPointStatus_Break: 1073 { 1074 BreakNode *p, *handle = (BreakNode *) * arg1; 1075 for (p = BreakList; p != NULL; p = p->next) 1076 if (p == handle) 1077 { 1078 *arg1 = -1; 1079 *arg2 = 1; 1080 return RDIError_NoError; 1081 } 1082 return RDIError_NoSuchPoint; 1083 } 1084 1085 case RDISet_RDILevel: 1086 if (*arg1 < LOWEST_RDI_LEVEL || *arg1 > HIGHEST_RDI_LEVEL) 1087 return RDIError_IncompatibleRDILevels; 1088 MYrdi_level = *arg1; 1089 return RDIError_NoError; 1090 1091 default: 1092 return RDIError_UnimplementedMessage; 1093 1094 } 1095} 1096 1097/***************************************************************************\ 1098* The emulator calls this routine at the beginning of every cycle when the * 1099* CallDebug flag is set. The second parameter passed is the address of the * 1100* currently executing instruction (i.e Program Counter - 8), the third * 1101* parameter is the instruction being executed. * 1102\***************************************************************************/ 1103 1104ARMword 1105ARMul_Debug (ARMul_State * state, ARMword pc, ARMword instr) 1106{ 1107 1108 if (state->EndCondition == RDIError_UserInterrupt) 1109 { 1110 TracePrint ((state, "User interrupt at %.8lx\n", pc)); 1111 state->CallDebug--; 1112 state->Emulate = STOP; 1113 } 1114 else 1115 { 1116 BreakNode *p = BreakList; 1117 for (; p != NULL; p = p->next) 1118 { 1119 switch (p->type) 1120 { 1121 case RDIPoint_EQ: 1122 if (pc == p->address) 1123 break; 1124 continue; 1125 case RDIPoint_GT: 1126 if (pc > p->address) 1127 break; 1128 continue; 1129 case RDIPoint_GE: 1130 if (pc >= p->address) 1131 break; 1132 continue; 1133 case RDIPoint_LT: 1134 if (pc < p->address) 1135 break; 1136 continue; 1137 case RDIPoint_LE: 1138 if (pc <= p->address) 1139 break; 1140 continue; 1141 case RDIPoint_IN: 1142 if (p->address <= pc && pc < p->address + p->bound) 1143 break; 1144 continue; 1145 case RDIPoint_OUT: 1146 if (p->address > pc || pc >= p->address + p->bound) 1147 break; 1148 continue; 1149 case RDIPoint_MASK: 1150 if ((pc & p->bound) == p->address) 1151 break; 1152 continue; 1153 } 1154 /* found a match */ 1155 TracePrint ((state, "Breakpoint reached at %.8lx\n", pc)); 1156 state->EndCondition = RDIError_BreakpointReached; 1157 state->Emulate = STOP; 1158 state->StopHandle = (ARMword) p; 1159 break; 1160 } 1161 } 1162 return instr; 1163} 1164 1165void 1166ARMul_CheckWatch (ARMul_State * state, ARMword addr, int access) 1167{ 1168 WatchNode *p; 1169 for (p = WatchList; p != NULL; p = p->next) 1170 if (p->datatype & access) 1171 { 1172 switch (p->type) 1173 { 1174 case RDIPoint_EQ: 1175 if (addr == p->address) 1176 break; 1177 continue; 1178 case RDIPoint_GT: 1179 if (addr > p->address) 1180 break; 1181 continue; 1182 case RDIPoint_GE: 1183 if (addr >= p->address) 1184 break; 1185 continue; 1186 case RDIPoint_LT: 1187 if (addr < p->address) 1188 break; 1189 continue; 1190 case RDIPoint_LE: 1191 if (addr <= p->address) 1192 break; 1193 continue; 1194 case RDIPoint_IN: 1195 if (p->address <= addr && addr < p->address + p->bound) 1196 break; 1197 continue; 1198 case RDIPoint_OUT: 1199 if (p->address > addr || addr >= p->address + p->bound) 1200 break; 1201 continue; 1202 case RDIPoint_MASK: 1203 if ((addr & p->bound) == p->address) 1204 break; 1205 continue; 1206 } 1207 /* found a match */ 1208 TracePrint ((state, "Watchpoint at %.8lx accessed\n", addr)); 1209 state->EndCondition = RDIError_WatchpointAccessed; 1210 state->Emulate = STOP; 1211 state->StopHandle = (ARMword) p; 1212 return; 1213 } 1214} 1215 1216static RDI_NameList const * 1217RDI_cpunames () 1218{ 1219 return (RDI_NameList const *) &processorconfig.count; 1220} 1221 1222const struct RDIProcVec armul_rdi = { 1223 "ARMUL", 1224 RDI_open, 1225 RDI_close, 1226 RDI_read, 1227 RDI_write, 1228 RDI_CPUread, 1229 RDI_CPUwrite, 1230 RDI_CPread, 1231 RDI_CPwrite, 1232 RDI_setbreak, 1233 RDI_clearbreak, 1234 RDI_setwatch, 1235 RDI_clearwatch, 1236 RDI_execute, 1237 RDI_step, 1238 RDI_info, 1239 1240 0, /*pointinq */ 1241 0, /*addconfig */ 1242 0, /*loadconfigdata */ 1243 0, /*selectconfig */ 1244 0, /*drivernames */ 1245 1246 RDI_cpunames 1247}; 1248