| OLD | NEW |
| (Empty) |
| 1 /* sh-stub.c -- debugging stub for the Renesas-SH. | |
| 2 | |
| 3 NOTE!! This code has to be compiled with optimization, otherwise the | |
| 4 function inlining which generates the exception handlers won't work. | |
| 5 | |
| 6 */ | |
| 7 | |
| 8 /* This is originally based on an m68k software stub written by Glenn | |
| 9 Engel at HP, but has changed quite a bit. | |
| 10 | |
| 11 Modifications for the SH by Ben Lee and Steve Chamberlain | |
| 12 | |
| 13 */ | |
| 14 | |
| 15 /**************************************************************************** | |
| 16 | |
| 17 THIS SOFTWARE IS NOT COPYRIGHTED | |
| 18 | |
| 19 HP offers the following for use in the public domain. HP makes no | |
| 20 warranty with regard to the software or it's performance and the | |
| 21 user accepts the software "AS IS" with all faults. | |
| 22 | |
| 23 HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD | |
| 24 TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
| 25 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
| 26 | |
| 27 ****************************************************************************/ | |
| 28 | |
| 29 | |
| 30 /* Remote communication protocol. | |
| 31 | |
| 32 A debug packet whose contents are <data> | |
| 33 is encapsulated for transmission in the form: | |
| 34 | |
| 35 $ <data> # CSUM1 CSUM2 | |
| 36 | |
| 37 <data> must be ASCII alphanumeric and cannot include characters | |
| 38 '$' or '#'. If <data> starts with two characters followed by | |
| 39 ':', then the existing stubs interpret this as a sequence number. | |
| 40 | |
| 41 CSUM1 and CSUM2 are ascii hex representation of an 8-bit | |
| 42 checksum of <data>, the most significant nibble is sent first. | |
| 43 the hex digits 0-9,a-f are used. | |
| 44 | |
| 45 Receiver responds with: | |
| 46 | |
| 47 + - if CSUM is correct and ready for next packet | |
| 48 - - if CSUM is incorrect | |
| 49 | |
| 50 <data> is as follows: | |
| 51 All values are encoded in ascii hex digits. | |
| 52 | |
| 53 Request Packet | |
| 54 | |
| 55 read registers g | |
| 56 reply XX....X Each byte of register data | |
| 57 is described by two hex digits. | |
| 58 Registers are in the internal order | |
| 59 for GDB, and the bytes in a register | |
| 60 are in the same order the machine uses. | |
| 61 or ENN for an error. | |
| 62 | |
| 63 write regs GXX..XX Each byte of register data | |
| 64 is described by two hex digits. | |
| 65 reply OK for success | |
| 66 ENN for an error | |
| 67 | |
| 68 write reg Pn...=r... Write register n... with value r..., | |
| 69 which contains two hex digits for each | |
| 70 byte in the register (target byte | |
| 71 order). | |
| 72 reply OK for success | |
| 73 ENN for an error | |
| 74 (not supported by all stubs). | |
| 75 | |
| 76 read mem mAA..AA,LLLL AA..AA is address, LLLL is length. | |
| 77 reply XX..XX XX..XX is mem contents | |
| 78 Can be fewer bytes than requested | |
| 79 if able to read only part of the data. | |
| 80 or ENN NN is errno | |
| 81 | |
| 82 write mem MAA..AA,LLLL:XX..XX | |
| 83 AA..AA is address, | |
| 84 LLLL is number of bytes, | |
| 85 XX..XX is data | |
| 86 reply OK for success | |
| 87 ENN for an error (this includes the case | |
| 88 where only part of the data was | |
| 89 written). | |
| 90 | |
| 91 cont cAA..AA AA..AA is address to resume | |
| 92 If AA..AA is omitted, | |
| 93 resume at same address. | |
| 94 | |
| 95 step sAA..AA AA..AA is address to resume | |
| 96 If AA..AA is omitted, | |
| 97 resume at same address. | |
| 98 | |
| 99 last signal ? Reply the current reason for stopping. | |
| 100 This is the same reply as is generated | |
| 101 for step or cont : SAA where AA is the | |
| 102 signal number. | |
| 103 | |
| 104 There is no immediate reply to step or cont. | |
| 105 The reply comes when the machine stops. | |
| 106 It is SAA AA is the "signal number" | |
| 107 | |
| 108 or... TAAn...:r...;n:r...;n...:r...; | |
| 109 AA = signal number | |
| 110 n... = register number | |
| 111 r... = register contents | |
| 112 or... WAA The process exited, and AA is | |
| 113 the exit status. This is only | |
| 114 applicable for certains sorts of | |
| 115 targets. | |
| 116 kill request k | |
| 117 | |
| 118 toggle debug d toggle debug flag (see 386 & 68k stubs) | |
| 119 reset r reset -- see sparc stub. | |
| 120 reserved <other> On other requests, the stub should | |
| 121 ignore the request and send an empty | |
| 122 response ($#<checksum>). This way | |
| 123 we can extend the protocol and GDB | |
| 124 can tell whether the stub it is | |
| 125 talking to uses the old or the new. | |
| 126 search tAA:PP,MM Search backwards starting at address | |
| 127 AA for a match with pattern PP and | |
| 128 mask MM. PP and MM are 4 bytes. | |
| 129 Not supported by all stubs. | |
| 130 | |
| 131 general query qXXXX Request info about XXXX. | |
| 132 general set QXXXX=yyyy Set value of XXXX to yyyy. | |
| 133 query sect offs qOffsets Get section offsets. Reply is | |
| 134 Text=xxx;Data=yyy;Bss=zzz | |
| 135 console output Otext Send text to stdout. Only comes from | |
| 136 remote target. | |
| 137 | |
| 138 Responses can be run-length encoded to save space. A '*' means that | |
| 139 the next character is an ASCII encoding giving a repeat count which | |
| 140 stands for that many repititions of the character preceding the '*'. | |
| 141 The encoding is n+29, yielding a printable character where n >=3 | |
| 142 (which is where rle starts to win). Don't use an n > 126. | |
| 143 | |
| 144 So | |
| 145 "0* " means the same as "0000". */ | |
| 146 | |
| 147 #include <string.h> | |
| 148 #include <setjmp.h> | |
| 149 | |
| 150 /* Renesas SH architecture instruction encoding masks */ | |
| 151 | |
| 152 #define COND_BR_MASK 0xff00 | |
| 153 #define UCOND_DBR_MASK 0xe000 | |
| 154 #define UCOND_RBR_MASK 0xf0df | |
| 155 #define TRAPA_MASK 0xff00 | |
| 156 | |
| 157 #define COND_DISP 0x00ff | |
| 158 #define UCOND_DISP 0x0fff | |
| 159 #define UCOND_REG 0x0f00 | |
| 160 | |
| 161 /* Renesas SH instruction opcodes */ | |
| 162 | |
| 163 #define BF_INSTR 0x8b00 | |
| 164 #define BT_INSTR 0x8900 | |
| 165 #define BRA_INSTR 0xa000 | |
| 166 #define BSR_INSTR 0xb000 | |
| 167 #define JMP_INSTR 0x402b | |
| 168 #define JSR_INSTR 0x400b | |
| 169 #define RTS_INSTR 0x000b | |
| 170 #define RTE_INSTR 0x002b | |
| 171 #define TRAPA_INSTR 0xc300 | |
| 172 #define SSTEP_INSTR 0xc3ff | |
| 173 | |
| 174 /* Renesas SH processor register masks */ | |
| 175 | |
| 176 #define T_BIT_MASK 0x0001 | |
| 177 | |
| 178 /* | |
| 179 * BUFMAX defines the maximum number of characters in inbound/outbound | |
| 180 * buffers. At least NUMREGBYTES*2 are needed for register packets. | |
| 181 */ | |
| 182 #define BUFMAX 1024 | |
| 183 | |
| 184 /* | |
| 185 * Number of bytes for registers | |
| 186 */ | |
| 187 #define NUMREGBYTES 112 /* 92 */ | |
| 188 | |
| 189 /* | |
| 190 * typedef | |
| 191 */ | |
| 192 typedef void (*Function) (); | |
| 193 | |
| 194 /* | |
| 195 * Forward declarations | |
| 196 */ | |
| 197 | |
| 198 static int hex (char); | |
| 199 static char *mem2hex (char *, char *, int); | |
| 200 static char *hex2mem (char *, char *, int); | |
| 201 static int hexToInt (char **, int *); | |
| 202 static unsigned char *getpacket (void); | |
| 203 static void putpacket (char *); | |
| 204 static void handle_buserror (void); | |
| 205 static int computeSignal (int exceptionVector); | |
| 206 static void handle_exception (int exceptionVector); | |
| 207 void init_serial(); | |
| 208 | |
| 209 void putDebugChar (char); | |
| 210 char getDebugChar (void); | |
| 211 | |
| 212 /* These are in the file but in asm statements so the compiler can't see them */ | |
| 213 void catch_exception_4 (void); | |
| 214 void catch_exception_6 (void); | |
| 215 void catch_exception_9 (void); | |
| 216 void catch_exception_10 (void); | |
| 217 void catch_exception_11 (void); | |
| 218 void catch_exception_32 (void); | |
| 219 void catch_exception_33 (void); | |
| 220 void catch_exception_255 (void); | |
| 221 | |
| 222 | |
| 223 | |
| 224 #define catch_exception_random catch_exception_255 /* Treat all odd ones like 25
5 */ | |
| 225 | |
| 226 void breakpoint (void); | |
| 227 | |
| 228 | |
| 229 #define init_stack_size 8*1024 /* if you change this you should also modify BIN
IT */ | |
| 230 #define stub_stack_size 8*1024 | |
| 231 | |
| 232 int init_stack[init_stack_size] __attribute__ ((section ("stack"))) = {0}; | |
| 233 int stub_stack[stub_stack_size] __attribute__ ((section ("stack"))) = {0}; | |
| 234 | |
| 235 | |
| 236 void INIT (); | |
| 237 void BINIT (); | |
| 238 | |
| 239 #define CPU_BUS_ERROR_VEC 9 | |
| 240 #define DMA_BUS_ERROR_VEC 10 | |
| 241 #define NMI_VEC 11 | |
| 242 #define INVALID_INSN_VEC 4 | |
| 243 #define INVALID_SLOT_VEC 6 | |
| 244 #define TRAP_VEC 32 | |
| 245 #define IO_VEC 33 | |
| 246 #define USER_VEC 255 | |
| 247 | |
| 248 | |
| 249 | |
| 250 char in_nmi; /* Set when handling an NMI, so we don't reenter */ | |
| 251 int dofault; /* Non zero, bus errors will raise exception */ | |
| 252 | |
| 253 int *stub_sp; | |
| 254 | |
| 255 /* debug > 0 prints ill-formed commands in valid packets & checksum errors */ | |
| 256 int remote_debug; | |
| 257 | |
| 258 /* jump buffer used for setjmp/longjmp */ | |
| 259 jmp_buf remcomEnv; | |
| 260 | |
| 261 enum regnames | |
| 262 { | |
| 263 R0, R1, R2, R3, R4, R5, R6, R7, | |
| 264 R8, R9, R10, R11, R12, R13, R14, | |
| 265 R15, PC, PR, GBR, VBR, MACH, MACL, SR, | |
| 266 TICKS, STALLS, CYCLES, INSTS, PLR | |
| 267 }; | |
| 268 | |
| 269 typedef struct | |
| 270 { | |
| 271 short *memAddr; | |
| 272 short oldInstr; | |
| 273 } | |
| 274 stepData; | |
| 275 | |
| 276 int registers[NUMREGBYTES / 4]; | |
| 277 stepData instrBuffer; | |
| 278 char stepped; | |
| 279 static const char hexchars[] = "0123456789abcdef"; | |
| 280 static char remcomInBuffer[BUFMAX]; | |
| 281 static char remcomOutBuffer[BUFMAX]; | |
| 282 | |
| 283 char highhex(int x) | |
| 284 { | |
| 285 return hexchars[(x >> 4) & 0xf]; | |
| 286 } | |
| 287 | |
| 288 char lowhex(int x) | |
| 289 { | |
| 290 return hexchars[x & 0xf]; | |
| 291 } | |
| 292 | |
| 293 /* | |
| 294 * Assembly macros | |
| 295 */ | |
| 296 | |
| 297 #define BREAKPOINT() asm("trapa #0x20"::); | |
| 298 | |
| 299 | |
| 300 /* | |
| 301 * Routines to handle hex data | |
| 302 */ | |
| 303 | |
| 304 static int | |
| 305 hex (char ch) | |
| 306 { | |
| 307 if ((ch >= 'a') && (ch <= 'f')) | |
| 308 return (ch - 'a' + 10); | |
| 309 if ((ch >= '0') && (ch <= '9')) | |
| 310 return (ch - '0'); | |
| 311 if ((ch >= 'A') && (ch <= 'F')) | |
| 312 return (ch - 'A' + 10); | |
| 313 return (-1); | |
| 314 } | |
| 315 | |
| 316 /* convert the memory, pointed to by mem into hex, placing result in buf */ | |
| 317 /* return a pointer to the last char put in buf (null) */ | |
| 318 static char * | |
| 319 mem2hex (char *mem, char *buf, int count) | |
| 320 { | |
| 321 int i; | |
| 322 int ch; | |
| 323 for (i = 0; i < count; i++) | |
| 324 { | |
| 325 ch = *mem++; | |
| 326 *buf++ = highhex (ch); | |
| 327 *buf++ = lowhex (ch); | |
| 328 } | |
| 329 *buf = 0; | |
| 330 return (buf); | |
| 331 } | |
| 332 | |
| 333 /* convert the hex array pointed to by buf into binary, to be placed in mem */ | |
| 334 /* return a pointer to the character after the last byte written */ | |
| 335 | |
| 336 static char * | |
| 337 hex2mem (char *buf, char *mem, int count) | |
| 338 { | |
| 339 int i; | |
| 340 unsigned char ch; | |
| 341 for (i = 0; i < count; i++) | |
| 342 { | |
| 343 ch = hex (*buf++) << 4; | |
| 344 ch = ch + hex (*buf++); | |
| 345 *mem++ = ch; | |
| 346 } | |
| 347 return (mem); | |
| 348 } | |
| 349 | |
| 350 /**********************************************/ | |
| 351 /* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */ | |
| 352 /* RETURN NUMBER OF CHARS PROCESSED */ | |
| 353 /**********************************************/ | |
| 354 static int | |
| 355 hexToInt (char **ptr, int *intValue) | |
| 356 { | |
| 357 int numChars = 0; | |
| 358 int hexValue; | |
| 359 | |
| 360 *intValue = 0; | |
| 361 | |
| 362 while (**ptr) | |
| 363 { | |
| 364 hexValue = hex (**ptr); | |
| 365 if (hexValue >= 0) | |
| 366 { | |
| 367 *intValue = (*intValue << 4) | hexValue; | |
| 368 numChars++; | |
| 369 } | |
| 370 else | |
| 371 break; | |
| 372 | |
| 373 (*ptr)++; | |
| 374 } | |
| 375 | |
| 376 return (numChars); | |
| 377 } | |
| 378 | |
| 379 /* | |
| 380 * Routines to get and put packets | |
| 381 */ | |
| 382 | |
| 383 /* scan for the sequence $<data>#<checksum> */ | |
| 384 | |
| 385 char * | |
| 386 getpacket (void) | |
| 387 { | |
| 388 unsigned char *buffer = &remcomInBuffer[0]; | |
| 389 unsigned char checksum; | |
| 390 unsigned char xmitcsum; | |
| 391 int count; | |
| 392 char ch; | |
| 393 | |
| 394 while (1) | |
| 395 { | |
| 396 /* wait around for the start character, ignore all other characters */ | |
| 397 while ((ch = getDebugChar ()) != '$') | |
| 398 ; | |
| 399 | |
| 400 retry: | |
| 401 checksum = 0; | |
| 402 xmitcsum = -1; | |
| 403 count = 0; | |
| 404 | |
| 405 /* now, read until a # or end of buffer is found */ | |
| 406 while (count < BUFMAX - 1) | |
| 407 { | |
| 408 ch = getDebugChar (); | |
| 409 if (ch == '$') | |
| 410 goto retry; | |
| 411 if (ch == '#') | |
| 412 break; | |
| 413 checksum = checksum + ch; | |
| 414 buffer[count] = ch; | |
| 415 count = count + 1; | |
| 416 } | |
| 417 buffer[count] = 0; | |
| 418 | |
| 419 if (ch == '#') | |
| 420 { | |
| 421 ch = getDebugChar (); | |
| 422 xmitcsum = hex (ch) << 4; | |
| 423 ch = getDebugChar (); | |
| 424 xmitcsum += hex (ch); | |
| 425 | |
| 426 if (checksum != xmitcsum) | |
| 427 { | |
| 428 putDebugChar ('-'); /* failed checksum */ | |
| 429 } | |
| 430 else | |
| 431 { | |
| 432 putDebugChar ('+'); /* successful transfer */ | |
| 433 | |
| 434 /* if a sequence char is present, reply the sequence ID */ | |
| 435 if (buffer[2] == ':') | |
| 436 { | |
| 437 putDebugChar (buffer[0]); | |
| 438 putDebugChar (buffer[1]); | |
| 439 | |
| 440 return &buffer[3]; | |
| 441 } | |
| 442 | |
| 443 return &buffer[0]; | |
| 444 } | |
| 445 } | |
| 446 } | |
| 447 } | |
| 448 | |
| 449 | |
| 450 /* send the packet in buffer. */ | |
| 451 | |
| 452 static void | |
| 453 putpacket (char *buffer) | |
| 454 { | |
| 455 int checksum; | |
| 456 int count; | |
| 457 | |
| 458 /* $<packet info>#<checksum>. */ | |
| 459 do | |
| 460 { | |
| 461 char *src = buffer; | |
| 462 putDebugChar ('$'); | |
| 463 checksum = 0; | |
| 464 | |
| 465 while (*src) | |
| 466 { | |
| 467 int runlen; | |
| 468 | |
| 469 /* Do run length encoding */ | |
| 470 for (runlen = 0; runlen < 100; runlen ++) | |
| 471 { | |
| 472 if (src[0] != src[runlen]) | |
| 473 { | |
| 474 if (runlen > 3) | |
| 475 { | |
| 476 int encode; | |
| 477 /* Got a useful amount */ | |
| 478 putDebugChar (*src); | |
| 479 checksum += *src; | |
| 480 putDebugChar ('*'); | |
| 481 checksum += '*'; | |
| 482 checksum += (encode = runlen + ' ' - 4); | |
| 483 putDebugChar (encode); | |
| 484 src += runlen; | |
| 485 } | |
| 486 else | |
| 487 { | |
| 488 putDebugChar (*src); | |
| 489 checksum += *src; | |
| 490 src++; | |
| 491 } | |
| 492 break; | |
| 493 } | |
| 494 } | |
| 495 } | |
| 496 | |
| 497 | |
| 498 putDebugChar ('#'); | |
| 499 putDebugChar (highhex(checksum)); | |
| 500 putDebugChar (lowhex(checksum)); | |
| 501 } | |
| 502 while (getDebugChar() != '+'); | |
| 503 } | |
| 504 | |
| 505 | |
| 506 /* a bus error has occurred, perform a longjmp | |
| 507 to return execution and allow handling of the error */ | |
| 508 | |
| 509 void | |
| 510 handle_buserror (void) | |
| 511 { | |
| 512 longjmp (remcomEnv, 1); | |
| 513 } | |
| 514 | |
| 515 /* | |
| 516 * this function takes the SH-1 exception number and attempts to | |
| 517 * translate this number into a unix compatible signal value | |
| 518 */ | |
| 519 static int | |
| 520 computeSignal (int exceptionVector) | |
| 521 { | |
| 522 int sigval; | |
| 523 switch (exceptionVector) | |
| 524 { | |
| 525 case INVALID_INSN_VEC: | |
| 526 sigval = 4; | |
| 527 break; | |
| 528 case INVALID_SLOT_VEC: | |
| 529 sigval = 4; | |
| 530 break; | |
| 531 case CPU_BUS_ERROR_VEC: | |
| 532 sigval = 10; | |
| 533 break; | |
| 534 case DMA_BUS_ERROR_VEC: | |
| 535 sigval = 10; | |
| 536 break; | |
| 537 case NMI_VEC: | |
| 538 sigval = 2; | |
| 539 break; | |
| 540 | |
| 541 case TRAP_VEC: | |
| 542 case USER_VEC: | |
| 543 sigval = 5; | |
| 544 break; | |
| 545 | |
| 546 default: | |
| 547 sigval = 7; /* "software generated"*/ | |
| 548 break; | |
| 549 } | |
| 550 return (sigval); | |
| 551 } | |
| 552 | |
| 553 void | |
| 554 doSStep (void) | |
| 555 { | |
| 556 short *instrMem; | |
| 557 int displacement; | |
| 558 int reg; | |
| 559 unsigned short opcode; | |
| 560 | |
| 561 instrMem = (short *) registers[PC]; | |
| 562 | |
| 563 opcode = *instrMem; | |
| 564 stepped = 1; | |
| 565 | |
| 566 if ((opcode & COND_BR_MASK) == BT_INSTR) | |
| 567 { | |
| 568 if (registers[SR] & T_BIT_MASK) | |
| 569 { | |
| 570 displacement = (opcode & COND_DISP) << 1; | |
| 571 if (displacement & 0x80) | |
| 572 displacement |= 0xffffff00; | |
| 573 /* | |
| 574 * Remember PC points to second instr. | |
| 575 * after PC of branch ... so add 4 | |
| 576 */ | |
| 577 instrMem = (short *) (registers[PC] + displacement + 4); | |
| 578 } | |
| 579 else | |
| 580 instrMem += 1; | |
| 581 } | |
| 582 else if ((opcode & COND_BR_MASK) == BF_INSTR) | |
| 583 { | |
| 584 if (registers[SR] & T_BIT_MASK) | |
| 585 instrMem += 1; | |
| 586 else | |
| 587 { | |
| 588 displacement = (opcode & COND_DISP) << 1; | |
| 589 if (displacement & 0x80) | |
| 590 displacement |= 0xffffff00; | |
| 591 /* | |
| 592 * Remember PC points to second instr. | |
| 593 * after PC of branch ... so add 4 | |
| 594 */ | |
| 595 instrMem = (short *) (registers[PC] + displacement + 4); | |
| 596 } | |
| 597 } | |
| 598 else if ((opcode & UCOND_DBR_MASK) == BRA_INSTR) | |
| 599 { | |
| 600 displacement = (opcode & UCOND_DISP) << 1; | |
| 601 if (displacement & 0x0800) | |
| 602 displacement |= 0xfffff000; | |
| 603 | |
| 604 /* | |
| 605 * Remember PC points to second instr. | |
| 606 * after PC of branch ... so add 4 | |
| 607 */ | |
| 608 instrMem = (short *) (registers[PC] + displacement + 4); | |
| 609 } | |
| 610 else if ((opcode & UCOND_RBR_MASK) == JSR_INSTR) | |
| 611 { | |
| 612 reg = (char) ((opcode & UCOND_REG) >> 8); | |
| 613 | |
| 614 instrMem = (short *) registers[reg]; | |
| 615 } | |
| 616 else if (opcode == RTS_INSTR) | |
| 617 instrMem = (short *) registers[PR]; | |
| 618 else if (opcode == RTE_INSTR) | |
| 619 instrMem = (short *) registers[15]; | |
| 620 else if ((opcode & TRAPA_MASK) == TRAPA_INSTR) | |
| 621 instrMem = (short *) ((opcode & ~TRAPA_MASK) << 2); | |
| 622 else | |
| 623 instrMem += 1; | |
| 624 | |
| 625 instrBuffer.memAddr = instrMem; | |
| 626 instrBuffer.oldInstr = *instrMem; | |
| 627 *instrMem = SSTEP_INSTR; | |
| 628 } | |
| 629 | |
| 630 | |
| 631 /* Undo the effect of a previous doSStep. If we single stepped, | |
| 632 restore the old instruction. */ | |
| 633 | |
| 634 void | |
| 635 undoSStep (void) | |
| 636 { | |
| 637 if (stepped) | |
| 638 { short *instrMem; | |
| 639 instrMem = instrBuffer.memAddr; | |
| 640 *instrMem = instrBuffer.oldInstr; | |
| 641 } | |
| 642 stepped = 0; | |
| 643 } | |
| 644 | |
| 645 /* | |
| 646 This function does all exception handling. It only does two things - | |
| 647 it figures out why it was called and tells gdb, and then it reacts | |
| 648 to gdb's requests. | |
| 649 | |
| 650 When in the monitor mode we talk a human on the serial line rather than gdb. | |
| 651 | |
| 652 */ | |
| 653 | |
| 654 | |
| 655 void | |
| 656 gdb_handle_exception (int exceptionVector) | |
| 657 { | |
| 658 int sigval, stepping; | |
| 659 int addr, length; | |
| 660 char *ptr; | |
| 661 | |
| 662 /* reply to host that an exception has occurred */ | |
| 663 sigval = computeSignal (exceptionVector); | |
| 664 remcomOutBuffer[0] = 'S'; | |
| 665 remcomOutBuffer[1] = highhex(sigval); | |
| 666 remcomOutBuffer[2] = lowhex (sigval); | |
| 667 remcomOutBuffer[3] = 0; | |
| 668 | |
| 669 putpacket (remcomOutBuffer); | |
| 670 | |
| 671 /* | |
| 672 * exception 255 indicates a software trap | |
| 673 * inserted in place of code ... so back up | |
| 674 * PC by one instruction, since this instruction | |
| 675 * will later be replaced by its original one! | |
| 676 */ | |
| 677 if (exceptionVector == 0xff | |
| 678 || exceptionVector == 0x20) | |
| 679 registers[PC] -= 2; | |
| 680 | |
| 681 /* | |
| 682 * Do the thangs needed to undo | |
| 683 * any stepping we may have done! | |
| 684 */ | |
| 685 undoSStep (); | |
| 686 | |
| 687 stepping = 0; | |
| 688 | |
| 689 while (1) | |
| 690 { | |
| 691 remcomOutBuffer[0] = 0; | |
| 692 ptr = getpacket (); | |
| 693 | |
| 694 switch (*ptr++) | |
| 695 { | |
| 696 case '?': | |
| 697 remcomOutBuffer[0] = 'S'; | |
| 698 remcomOutBuffer[1] = highhex (sigval); | |
| 699 remcomOutBuffer[2] = lowhex (sigval); | |
| 700 remcomOutBuffer[3] = 0; | |
| 701 break; | |
| 702 case 'd': | |
| 703 remote_debug = !(remote_debug); /* toggle debug flag */ | |
| 704 break; | |
| 705 case 'g': /* return the value of the CPU registers */ | |
| 706 mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES); | |
| 707 break; | |
| 708 case 'G': /* set the value of the CPU registers - return O
K */ | |
| 709 hex2mem (ptr, (char *) registers, NUMREGBYTES); | |
| 710 strcpy (remcomOutBuffer, "OK"); | |
| 711 break; | |
| 712 | |
| 713 /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ | |
| 714 case 'm': | |
| 715 if (setjmp (remcomEnv) == 0) | |
| 716 { | |
| 717 dofault = 0; | |
| 718 /* TRY, TO READ %x,%x. IF SUCCEED, SET PTR = 0 */ | |
| 719 if (hexToInt (&ptr, &addr)) | |
| 720 if (*(ptr++) == ',') | |
| 721 if (hexToInt (&ptr, &length)) | |
| 722 { | |
| 723 ptr = 0; | |
| 724 mem2hex ((char *) addr, remcomOutBuffer, length); | |
| 725 } | |
| 726 if (ptr) | |
| 727 strcpy (remcomOutBuffer, "E01"); | |
| 728 } | |
| 729 else | |
| 730 strcpy (remcomOutBuffer, "E03"); | |
| 731 | |
| 732 /* restore handler for bus error */ | |
| 733 dofault = 1; | |
| 734 break; | |
| 735 | |
| 736 /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ | |
| 737 case 'M': | |
| 738 if (setjmp (remcomEnv) == 0) | |
| 739 { | |
| 740 dofault = 0; | |
| 741 | |
| 742 /* TRY, TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */ | |
| 743 if (hexToInt (&ptr, &addr)) | |
| 744 if (*(ptr++) == ',') | |
| 745 if (hexToInt (&ptr, &length)) | |
| 746 if (*(ptr++) == ':') | |
| 747 { | |
| 748 hex2mem (ptr, (char *) addr, length); | |
| 749 ptr = 0; | |
| 750 strcpy (remcomOutBuffer, "OK"); | |
| 751 } | |
| 752 if (ptr) | |
| 753 strcpy (remcomOutBuffer, "E02"); | |
| 754 } | |
| 755 else | |
| 756 strcpy (remcomOutBuffer, "E03"); | |
| 757 | |
| 758 /* restore handler for bus error */ | |
| 759 dofault = 1; | |
| 760 break; | |
| 761 | |
| 762 /* cAA..AA Continue at address AA..AA(optional) */ | |
| 763 /* sAA..AA Step one instruction from AA..AA(optional) */ | |
| 764 case 's': | |
| 765 stepping = 1; | |
| 766 case 'c': | |
| 767 { | |
| 768 /* tRY, to read optional parameter, pc unchanged if no parm */ | |
| 769 if (hexToInt (&ptr, &addr)) | |
| 770 registers[PC] = addr; | |
| 771 | |
| 772 if (stepping) | |
| 773 doSStep (); | |
| 774 } | |
| 775 return; | |
| 776 break; | |
| 777 | |
| 778 /* kill the program */ | |
| 779 case 'k': /* do nothing */ | |
| 780 break; | |
| 781 } /* switch */ | |
| 782 | |
| 783 /* reply to the request */ | |
| 784 putpacket (remcomOutBuffer); | |
| 785 } | |
| 786 } | |
| 787 | |
| 788 | |
| 789 #define GDBCOOKIE 0x5ac | |
| 790 static int ingdbmode; | |
| 791 /* We've had an exception - choose to go into the monitor or | |
| 792 the gdb stub */ | |
| 793 void handle_exception(int exceptionVector) | |
| 794 { | |
| 795 #ifdef MONITOR | |
| 796 if (ingdbmode != GDBCOOKIE) | |
| 797 monitor_handle_exception (exceptionVector); | |
| 798 else | |
| 799 #endif | |
| 800 gdb_handle_exception (exceptionVector); | |
| 801 | |
| 802 } | |
| 803 | |
| 804 void | |
| 805 gdb_mode (void) | |
| 806 { | |
| 807 ingdbmode = GDBCOOKIE; | |
| 808 breakpoint(); | |
| 809 } | |
| 810 /* This function will generate a breakpoint exception. It is used at the | |
| 811 beginning of a program to sync up with a debugger and can be used | |
| 812 otherwise as a quick means to stop program execution and "break" into | |
| 813 the debugger. */ | |
| 814 | |
| 815 void | |
| 816 breakpoint (void) | |
| 817 { | |
| 818 BREAKPOINT (); | |
| 819 } | |
| 820 | |
| 821 /**** Processor-specific routines start here ****/ | |
| 822 /**** Processor-specific routines start here ****/ | |
| 823 /**** Processor-specific routines start here ****/ | |
| 824 | |
| 825 /* Note: | |
| 826 | |
| 827 The Renesas SH family uses two exception architectures: | |
| 828 | |
| 829 SH1 & SH2: | |
| 830 | |
| 831 These processors utilize an exception vector table. | |
| 832 Exceptions are vectored to the address stored at VBR + (exception_num * 4
) | |
| 833 | |
| 834 SH3, SH3E, & SH4: | |
| 835 | |
| 836 These processors have fixed entry points relative to the VBR for | |
| 837 various exception classes. | |
| 838 */ | |
| 839 | |
| 840 #if defined(__sh1__) || defined(__sh2__) | |
| 841 | |
| 842 /* SH1/SH2 exception vector table format */ | |
| 843 | |
| 844 typedef struct | |
| 845 { | |
| 846 void (*func_cold) (); | |
| 847 int *stack_cold; | |
| 848 void (*func_warm) (); | |
| 849 int *stack_warm; | |
| 850 void (*(handler[256 - 4])) (); | |
| 851 } | |
| 852 vec_type; | |
| 853 | |
| 854 /* vectable is the SH1/SH2 vector table. It must be at address 0 | |
| 855 or wherever your vbr points. */ | |
| 856 | |
| 857 const vec_type vectable = | |
| 858 { | |
| 859 &BINIT, /* 0: Power-on reset PC */ | |
| 860 init_stack + init_stack_size, /* 1: Power-on reset SP */ | |
| 861 &BINIT, /* 2: Manual reset PC */ | |
| 862 init_stack + init_stack_size, /* 3: Manual reset SP */ | |
| 863 { | |
| 864 &catch_exception_4, /* 4: General invalid instruction */ | |
| 865 &catch_exception_random, /* 5: Reserved for system */ | |
| 866 &catch_exception_6, /* 6: Invalid slot instruction */ | |
| 867 &catch_exception_random, /* 7: Reserved for system */ | |
| 868 &catch_exception_random, /* 8: Reserved for system */ | |
| 869 &catch_exception_9, /* 9: CPU bus error */ | |
| 870 &catch_exception_10, /* 10: DMA bus error */ | |
| 871 &catch_exception_11, /* 11: NMI */ | |
| 872 &catch_exception_random, /* 12: User break */ | |
| 873 &catch_exception_random, /* 13: Reserved for system */ | |
| 874 &catch_exception_random, /* 14: Reserved for system */ | |
| 875 &catch_exception_random, /* 15: Reserved for system */ | |
| 876 &catch_exception_random, /* 16: Reserved for system */ | |
| 877 &catch_exception_random, /* 17: Reserved for system */ | |
| 878 &catch_exception_random, /* 18: Reserved for system */ | |
| 879 &catch_exception_random, /* 19: Reserved for system */ | |
| 880 &catch_exception_random, /* 20: Reserved for system */ | |
| 881 &catch_exception_random, /* 21: Reserved for system */ | |
| 882 &catch_exception_random, /* 22: Reserved for system */ | |
| 883 &catch_exception_random, /* 23: Reserved for system */ | |
| 884 &catch_exception_random, /* 24: Reserved for system */ | |
| 885 &catch_exception_random, /* 25: Reserved for system */ | |
| 886 &catch_exception_random, /* 26: Reserved for system */ | |
| 887 &catch_exception_random, /* 27: Reserved for system */ | |
| 888 &catch_exception_random, /* 28: Reserved for system */ | |
| 889 &catch_exception_random, /* 29: Reserved for system */ | |
| 890 &catch_exception_random, /* 30: Reserved for system */ | |
| 891 &catch_exception_random, /* 31: Reserved for system */ | |
| 892 &catch_exception_32, /* 32: Trap instr (user vectors) */ | |
| 893 &catch_exception_33, /* 33: Trap instr (user vectors) */ | |
| 894 &catch_exception_random, /* 34: Trap instr (user vectors) */ | |
| 895 &catch_exception_random, /* 35: Trap instr (user vectors) */ | |
| 896 &catch_exception_random, /* 36: Trap instr (user vectors) */ | |
| 897 &catch_exception_random, /* 37: Trap instr (user vectors) */ | |
| 898 &catch_exception_random, /* 38: Trap instr (user vectors) */ | |
| 899 &catch_exception_random, /* 39: Trap instr (user vectors) */ | |
| 900 &catch_exception_random, /* 40: Trap instr (user vectors) */ | |
| 901 &catch_exception_random, /* 41: Trap instr (user vectors) */ | |
| 902 &catch_exception_random, /* 42: Trap instr (user vectors) */ | |
| 903 &catch_exception_random, /* 43: Trap instr (user vectors) */ | |
| 904 &catch_exception_random, /* 44: Trap instr (user vectors) */ | |
| 905 &catch_exception_random, /* 45: Trap instr (user vectors) */ | |
| 906 &catch_exception_random, /* 46: Trap instr (user vectors) */ | |
| 907 &catch_exception_random, /* 47: Trap instr (user vectors) */ | |
| 908 &catch_exception_random, /* 48: Trap instr (user vectors) */ | |
| 909 &catch_exception_random, /* 49: Trap instr (user vectors) */ | |
| 910 &catch_exception_random, /* 50: Trap instr (user vectors) */ | |
| 911 &catch_exception_random, /* 51: Trap instr (user vectors) */ | |
| 912 &catch_exception_random, /* 52: Trap instr (user vectors) */ | |
| 913 &catch_exception_random, /* 53: Trap instr (user vectors) */ | |
| 914 &catch_exception_random, /* 54: Trap instr (user vectors) */ | |
| 915 &catch_exception_random, /* 55: Trap instr (user vectors) */ | |
| 916 &catch_exception_random, /* 56: Trap instr (user vectors) */ | |
| 917 &catch_exception_random, /* 57: Trap instr (user vectors) */ | |
| 918 &catch_exception_random, /* 58: Trap instr (user vectors) */ | |
| 919 &catch_exception_random, /* 59: Trap instr (user vectors) */ | |
| 920 &catch_exception_random, /* 60: Trap instr (user vectors) */ | |
| 921 &catch_exception_random, /* 61: Trap instr (user vectors) */ | |
| 922 &catch_exception_random, /* 62: Trap instr (user vectors) */ | |
| 923 &catch_exception_random, /* 63: Trap instr (user vectors) */ | |
| 924 &catch_exception_random, /* 64: IRQ0 */ | |
| 925 &catch_exception_random, /* 65: IRQ1 */ | |
| 926 &catch_exception_random, /* 66: IRQ2 */ | |
| 927 &catch_exception_random, /* 67: IRQ3 */ | |
| 928 &catch_exception_random, /* 68: IRQ4 */ | |
| 929 &catch_exception_random, /* 69: IRQ5 */ | |
| 930 &catch_exception_random, /* 70: IRQ6 */ | |
| 931 &catch_exception_random, /* 71: IRQ7 */ | |
| 932 &catch_exception_random, | |
| 933 &catch_exception_random, | |
| 934 &catch_exception_random, | |
| 935 &catch_exception_random, | |
| 936 &catch_exception_random, | |
| 937 &catch_exception_random, | |
| 938 &catch_exception_random, | |
| 939 &catch_exception_random, | |
| 940 &catch_exception_random, | |
| 941 &catch_exception_random, | |
| 942 &catch_exception_random, | |
| 943 &catch_exception_random, | |
| 944 &catch_exception_random, | |
| 945 &catch_exception_random, | |
| 946 &catch_exception_random, | |
| 947 &catch_exception_random, | |
| 948 &catch_exception_random, | |
| 949 &catch_exception_random, | |
| 950 &catch_exception_random, | |
| 951 &catch_exception_random, | |
| 952 &catch_exception_random, | |
| 953 &catch_exception_random, | |
| 954 &catch_exception_random, | |
| 955 &catch_exception_random, | |
| 956 &catch_exception_random, | |
| 957 &catch_exception_random, | |
| 958 &catch_exception_random, | |
| 959 &catch_exception_random, | |
| 960 &catch_exception_random, | |
| 961 &catch_exception_random, | |
| 962 &catch_exception_random, | |
| 963 &catch_exception_random, | |
| 964 &catch_exception_random, | |
| 965 &catch_exception_random, | |
| 966 &catch_exception_random, | |
| 967 &catch_exception_random, | |
| 968 &catch_exception_random, | |
| 969 &catch_exception_random, | |
| 970 &catch_exception_random, | |
| 971 &catch_exception_random, | |
| 972 &catch_exception_random, | |
| 973 &catch_exception_random, | |
| 974 &catch_exception_random, | |
| 975 &catch_exception_random, | |
| 976 &catch_exception_random, | |
| 977 &catch_exception_random, | |
| 978 &catch_exception_random, | |
| 979 &catch_exception_random, | |
| 980 &catch_exception_random, | |
| 981 &catch_exception_random, | |
| 982 &catch_exception_random, | |
| 983 &catch_exception_random, | |
| 984 &catch_exception_random, | |
| 985 &catch_exception_random, | |
| 986 &catch_exception_random, | |
| 987 &catch_exception_random, | |
| 988 &catch_exception_random, | |
| 989 &catch_exception_random, | |
| 990 &catch_exception_random, | |
| 991 &catch_exception_random, | |
| 992 &catch_exception_random, | |
| 993 &catch_exception_random, | |
| 994 &catch_exception_random, | |
| 995 &catch_exception_random, | |
| 996 &catch_exception_random, | |
| 997 &catch_exception_random, | |
| 998 &catch_exception_random, | |
| 999 &catch_exception_random, | |
| 1000 &catch_exception_random, | |
| 1001 &catch_exception_random, | |
| 1002 &catch_exception_random, | |
| 1003 &catch_exception_random, | |
| 1004 &catch_exception_random, | |
| 1005 &catch_exception_random, | |
| 1006 &catch_exception_random, | |
| 1007 &catch_exception_random, | |
| 1008 &catch_exception_random, | |
| 1009 &catch_exception_random, | |
| 1010 &catch_exception_random, | |
| 1011 &catch_exception_random, | |
| 1012 &catch_exception_random, | |
| 1013 &catch_exception_random, | |
| 1014 &catch_exception_random, | |
| 1015 &catch_exception_random, | |
| 1016 &catch_exception_random, | |
| 1017 &catch_exception_random, | |
| 1018 &catch_exception_random, | |
| 1019 &catch_exception_random, | |
| 1020 &catch_exception_random, | |
| 1021 &catch_exception_random, | |
| 1022 &catch_exception_random, | |
| 1023 &catch_exception_random, | |
| 1024 &catch_exception_random, | |
| 1025 &catch_exception_random, | |
| 1026 &catch_exception_random, | |
| 1027 &catch_exception_random, | |
| 1028 &catch_exception_random, | |
| 1029 &catch_exception_random, | |
| 1030 &catch_exception_random, | |
| 1031 &catch_exception_random, | |
| 1032 &catch_exception_random, | |
| 1033 &catch_exception_random, | |
| 1034 &catch_exception_random, | |
| 1035 &catch_exception_random, | |
| 1036 &catch_exception_random, | |
| 1037 &catch_exception_random, | |
| 1038 &catch_exception_random, | |
| 1039 &catch_exception_random, | |
| 1040 &catch_exception_random, | |
| 1041 &catch_exception_random, | |
| 1042 &catch_exception_random, | |
| 1043 &catch_exception_random, | |
| 1044 &catch_exception_random, | |
| 1045 &catch_exception_random, | |
| 1046 &catch_exception_random, | |
| 1047 &catch_exception_random, | |
| 1048 &catch_exception_random, | |
| 1049 &catch_exception_random, | |
| 1050 &catch_exception_random, | |
| 1051 &catch_exception_random, | |
| 1052 &catch_exception_random, | |
| 1053 &catch_exception_random, | |
| 1054 &catch_exception_random, | |
| 1055 &catch_exception_random, | |
| 1056 &catch_exception_random, | |
| 1057 &catch_exception_random, | |
| 1058 &catch_exception_random, | |
| 1059 &catch_exception_random, | |
| 1060 &catch_exception_random, | |
| 1061 &catch_exception_random, | |
| 1062 &catch_exception_random, | |
| 1063 &catch_exception_random, | |
| 1064 &catch_exception_random, | |
| 1065 &catch_exception_random, | |
| 1066 &catch_exception_random, | |
| 1067 &catch_exception_random, | |
| 1068 &catch_exception_random, | |
| 1069 &catch_exception_random, | |
| 1070 &catch_exception_random, | |
| 1071 &catch_exception_random, | |
| 1072 &catch_exception_random, | |
| 1073 &catch_exception_random, | |
| 1074 &catch_exception_random, | |
| 1075 &catch_exception_random, | |
| 1076 &catch_exception_random, | |
| 1077 &catch_exception_random, | |
| 1078 &catch_exception_random, | |
| 1079 &catch_exception_random, | |
| 1080 &catch_exception_random, | |
| 1081 &catch_exception_random, | |
| 1082 &catch_exception_random, | |
| 1083 &catch_exception_random, | |
| 1084 &catch_exception_random, | |
| 1085 &catch_exception_random, | |
| 1086 &catch_exception_random, | |
| 1087 &catch_exception_random, | |
| 1088 &catch_exception_random, | |
| 1089 &catch_exception_random, | |
| 1090 &catch_exception_random, | |
| 1091 &catch_exception_random, | |
| 1092 &catch_exception_random, | |
| 1093 &catch_exception_random, | |
| 1094 &catch_exception_random, | |
| 1095 &catch_exception_random, | |
| 1096 &catch_exception_random, | |
| 1097 &catch_exception_random, | |
| 1098 &catch_exception_random, | |
| 1099 &catch_exception_random, | |
| 1100 &catch_exception_random, | |
| 1101 &catch_exception_random, | |
| 1102 &catch_exception_random, | |
| 1103 &catch_exception_random, | |
| 1104 &catch_exception_random, | |
| 1105 &catch_exception_random, | |
| 1106 &catch_exception_random, | |
| 1107 &catch_exception_random, | |
| 1108 &catch_exception_random, | |
| 1109 &catch_exception_random, | |
| 1110 &catch_exception_random, | |
| 1111 &catch_exception_random, | |
| 1112 &catch_exception_random, | |
| 1113 &catch_exception_random, | |
| 1114 &catch_exception_random, | |
| 1115 &catch_exception_255}}; | |
| 1116 | |
| 1117 #define BCR (*(volatile short *)(0x05FFFFA0)) /* Bus control register */ | |
| 1118 #define BAS (0x800) /* Byte access select */ | |
| 1119 #define WCR1 (*(volatile short *)(0x05ffffA2)) /* Wait state control register */ | |
| 1120 | |
| 1121 asm ("_BINIT: mov.l L1,r15"); | |
| 1122 asm ("bra _INIT"); | |
| 1123 asm ("nop"); | |
| 1124 asm ("L1: .long _init_stack + 8*1024*4"); | |
| 1125 void | |
| 1126 INIT (void) | |
| 1127 { | |
| 1128 /* First turn on the ram */ | |
| 1129 WCR1 = 0; /* Never sample wait */ | |
| 1130 BCR = BAS; /* use lowbyte/high byte */ | |
| 1131 | |
| 1132 init_serial(); | |
| 1133 | |
| 1134 #ifdef MONITOR | |
| 1135 reset_hook (); | |
| 1136 #endif | |
| 1137 | |
| 1138 | |
| 1139 in_nmi = 0; | |
| 1140 dofault = 1; | |
| 1141 stepped = 0; | |
| 1142 | |
| 1143 stub_sp = stub_stack + stub_stack_size; | |
| 1144 breakpoint (); | |
| 1145 | |
| 1146 while (1) | |
| 1147 ; | |
| 1148 } | |
| 1149 | |
| 1150 | |
| 1151 static void sr() | |
| 1152 { | |
| 1153 | |
| 1154 | |
| 1155 /* Calling Reset does the same as pressing the button */ | |
| 1156 asm (".global _Reset | |
| 1157 .global _WarmReset | |
| 1158 _Reset: | |
| 1159 _WarmReset: | |
| 1160 mov.l L_sp,r15 | |
| 1161 bra _INIT | |
| 1162 nop | |
| 1163 .align 2 | |
| 1164 L_sp: .long _init_stack + 8000"); | |
| 1165 | |
| 1166 asm("saveRegisters: | |
| 1167 mov.l @(L_reg, pc), r0 | |
| 1168 mov.l @r15+, r1 ! pop R0 | |
| 1169 mov.l r2, @(0x08, r0) ! save R2 | |
| 1170 mov.l r1, @r0 ! save R0 | |
| 1171 mov.l @r15+, r1 ! pop R1 | |
| 1172 mov.l r3, @(0x0c, r0) ! save R3 | |
| 1173 mov.l r1, @(0x04, r0) ! save R1 | |
| 1174 mov.l r4, @(0x10, r0) ! save R4 | |
| 1175 mov.l r5, @(0x14, r0) ! save R5 | |
| 1176 mov.l r6, @(0x18, r0) ! save R6 | |
| 1177 mov.l r7, @(0x1c, r0) ! save R7 | |
| 1178 mov.l r8, @(0x20, r0) ! save R8 | |
| 1179 mov.l r9, @(0x24, r0) ! save R9 | |
| 1180 mov.l r10, @(0x28, r0) ! save R10 | |
| 1181 mov.l r11, @(0x2c, r0) ! save R11 | |
| 1182 mov.l r12, @(0x30, r0) ! save R12 | |
| 1183 mov.l r13, @(0x34, r0) ! save R13 | |
| 1184 mov.l r14, @(0x38, r0) ! save R14 | |
| 1185 mov.l @r15+, r4 ! save arg to handleExce
ption | |
| 1186 add #8, r15 ! hide PC/SR values on s
tack | |
| 1187 mov.l r15, @(0x3c, r0) ! save R15 | |
| 1188 add #-8, r15 ! save still needs old S
P value | |
| 1189 add #92, r0 ! readjust register poin
ter | |
| 1190 mov r15, r2 | |
| 1191 add #4, r2 | |
| 1192 mov.l @r2, r2 ! R2 has SR | |
| 1193 mov.l @r15, r1 ! R1 has PC | |
| 1194 mov.l r2, @-r0 ! save SR | |
| 1195 sts.l macl, @-r0 ! save MACL | |
| 1196 sts.l mach, @-r0 ! save MACH | |
| 1197 stc.l vbr, @-r0 ! save VBR | |
| 1198 stc.l gbr, @-r0 ! save GBR | |
| 1199 sts.l pr, @-r0 ! save PR | |
| 1200 mov.l @(L_stubstack, pc), r2 | |
| 1201 mov.l @(L_hdl_except, pc), r3 | |
| 1202 mov.l @r2, r15 | |
| 1203 jsr @r3 | |
| 1204 mov.l r1, @-r0 ! save PC | |
| 1205 mov.l @(L_stubstack, pc), r0 | |
| 1206 mov.l @(L_reg, pc), r1 | |
| 1207 bra restoreRegisters | |
| 1208 mov.l r15, @r0 ! save __stub_stack | |
| 1209 | |
| 1210 .align 2 | |
| 1211 L_reg: | |
| 1212 .long _registers | |
| 1213 L_stubstack: | |
| 1214 .long _stub_sp | |
| 1215 L_hdl_except: | |
| 1216 .long _handle_exception"); | |
| 1217 | |
| 1218 } | |
| 1219 | |
| 1220 static void rr() | |
| 1221 { | |
| 1222 asm(" | |
| 1223 .align 2 | |
| 1224 .global _resume | |
| 1225 _resume: | |
| 1226 mov r4,r1 | |
| 1227 restoreRegisters: | |
| 1228 add #8, r1 ! skip to R2 | |
| 1229 mov.l @r1+, r2 ! restore R2 | |
| 1230 mov.l @r1+, r3 ! restore R3 | |
| 1231 mov.l @r1+, r4 ! restore R4 | |
| 1232 mov.l @r1+, r5 ! restore R5 | |
| 1233 mov.l @r1+, r6 ! restore R6 | |
| 1234 mov.l @r1+, r7 ! restore R7 | |
| 1235 mov.l @r1+, r8 ! restore R8 | |
| 1236 mov.l @r1+, r9 ! restore R9 | |
| 1237 mov.l @r1+, r10 ! restore R10 | |
| 1238 mov.l @r1+, r11 ! restore R11 | |
| 1239 mov.l @r1+, r12 ! restore R12 | |
| 1240 mov.l @r1+, r13 ! restore R13 | |
| 1241 mov.l @r1+, r14 ! restore R14 | |
| 1242 mov.l @r1+, r15 ! restore progra
ms stack | |
| 1243 mov.l @r1+, r0 | |
| 1244 add #-8, r15 ! uncover PC/SR
on stack | |
| 1245 mov.l r0, @r15 ! restore PC ont
o stack | |
| 1246 lds.l @r1+, pr ! restore PR | |
| 1247 ldc.l @r1+, gbr ! restore GBR
| |
| 1248 ldc.l @r1+, vbr ! restore VBR | |
| 1249 lds.l @r1+, mach ! restore MACH | |
| 1250 lds.l @r1+, macl ! restore MACL | |
| 1251 mov.l @r1, r0 | |
| 1252 add #-88, r1 ! readjust reg p
ointer to R1 | |
| 1253 mov.l r0, @(4, r15) ! restore SR ont
o stack+4 | |
| 1254 mov.l r2, @-r15 | |
| 1255 mov.l L_in_nmi, r0 | |
| 1256 mov #0, r2 | |
| 1257 mov.b r2, @r0 | |
| 1258 mov.l @r15+, r2 | |
| 1259 mov.l @r1+, r0 ! restore R0 | |
| 1260 rte | |
| 1261 mov.l @r1, r1 ! restore R1 | |
| 1262 | |
| 1263 "); | |
| 1264 } | |
| 1265 | |
| 1266 | |
| 1267 static __inline__ void code_for_catch_exception(int n) | |
| 1268 { | |
| 1269 asm(" .globl _catch_exception_%O0" : : "i" (n)
); | |
| 1270 asm(" _catch_exception_%O0:" :: "i" (n)
); | |
| 1271 | |
| 1272 asm(" add #-4, r15 ! reserve spot o
n stack "); | |
| 1273 asm(" mov.l r1, @-r15 ! push R1
"); | |
| 1274 | |
| 1275 if (n == NMI_VEC) | |
| 1276 { | |
| 1277 /* Special case for NMI - make sure that they don't nest */ | |
| 1278 asm(" mov.l r0, @-r15 ! push R
0"); | |
| 1279 asm(" mov.l L_in_nmi, r0"); | |
| 1280 asm(" tas.b @r0 ! Fend o
ff against addtnl NMIs"); | |
| 1281 asm(" bt noNMI"); | |
| 1282 asm(" mov.l @r15+, r0"); | |
| 1283 asm(" mov.l @r15+, r1"); | |
| 1284 asm(" add #4, r15"); | |
| 1285 asm(" rte"); | |
| 1286 asm(" nop"); | |
| 1287 asm(".align 2"); | |
| 1288 asm("L_in_nmi: .long _in_nmi"); | |
| 1289 asm("noNMI:"); | |
| 1290 } | |
| 1291 else | |
| 1292 { | |
| 1293 | |
| 1294 if (n == CPU_BUS_ERROR_VEC) | |
| 1295 { | |
| 1296 /* Exception 9 (bus errors) are disasbleable - so that you | |
| 1297 can probe memory and get zero instead of a fault. | |
| 1298 Because the vector table may be in ROM we don't revector | |
| 1299 the interrupt like all the other stubs, we check in here | |
| 1300 */ | |
| 1301 asm("mov.l L_dofault,r1"); | |
| 1302 asm("mov.l @r1,r1"); | |
| 1303 asm("tst r1,r1"); | |
| 1304 asm("bf faultaway"); | |
| 1305 asm("bsr _handle_buserror"); | |
| 1306 asm(".align 2"); | |
| 1307 asm("L_dofault: .long _dofault"); | |
| 1308 asm("faultaway:"); | |
| 1309 } | |
| 1310 asm(" mov #15<<4, r1
"); | |
| 1311 asm(" ldc r1, sr ! disabl
e interrupts "); | |
| 1312 asm(" mov.l r0, @-r15 ! push R
0 "); | |
| 1313 } | |
| 1314 | |
| 1315 /* Prepare for saving context, we've already pushed r0 and r1, stick exception
number | |
| 1316 into the frame */ | |
| 1317 asm(" mov r15, r0
"); | |
| 1318 asm(" add #8, r0
"); | |
| 1319 asm(" mov %0,r1" :: "i" (n)
); | |
| 1320 asm(" extu.b r1,r1
"); | |
| 1321 asm(" bra saveRegisters ! save register
values "); | |
| 1322 asm(" mov.l r1, @r0 ! save exception
# "); | |
| 1323 } | |
| 1324 | |
| 1325 | |
| 1326 static void | |
| 1327 exceptions (void) | |
| 1328 { | |
| 1329 code_for_catch_exception (CPU_BUS_ERROR_VEC); | |
| 1330 code_for_catch_exception (DMA_BUS_ERROR_VEC); | |
| 1331 code_for_catch_exception (INVALID_INSN_VEC); | |
| 1332 code_for_catch_exception (INVALID_SLOT_VEC); | |
| 1333 code_for_catch_exception (NMI_VEC); | |
| 1334 code_for_catch_exception (TRAP_VEC); | |
| 1335 code_for_catch_exception (USER_VEC); | |
| 1336 code_for_catch_exception (IO_VEC); | |
| 1337 } | |
| 1338 | |
| 1339 | |
| 1340 | |
| 1341 | |
| 1342 | |
| 1343 | |
| 1344 /* Support for Serial I/O using on chip uart */ | |
| 1345 | |
| 1346 #define SMR0 (*(volatile char *)(0x05FFFEC0)) /* Channel 0 serial mode register
*/ | |
| 1347 #define BRR0 (*(volatile char *)(0x05FFFEC1)) /* Channel 0 bit rate register */ | |
| 1348 #define SCR0 (*(volatile char *)(0x05FFFEC2)) /* Channel 0 serial control regis
ter */ | |
| 1349 #define TDR0 (*(volatile char *)(0x05FFFEC3)) /* Channel 0 transmit data regist
er */ | |
| 1350 #define SSR0 (*(volatile char *)(0x05FFFEC4)) /* Channel 0 serial status regist
er */ | |
| 1351 #define RDR0 (*(volatile char *)(0x05FFFEC5)) /* Channel 0 receive data registe
r */ | |
| 1352 | |
| 1353 #define SMR1 (*(volatile char *)(0x05FFFEC8)) /* Channel 1 serial mode register
*/ | |
| 1354 #define BRR1 (*(volatile char *)(0x05FFFEC9)) /* Channel 1 bit rate register */ | |
| 1355 #define SCR1 (*(volatile char *)(0x05FFFECA)) /* Channel 1 serial control regis
ter */ | |
| 1356 #define TDR1 (*(volatile char *)(0x05FFFECB)) /* Channel 1 transmit data regist
er */ | |
| 1357 #define SSR1 (*(volatile char *)(0x05FFFECC)) /* Channel 1 serial status regist
er */ | |
| 1358 #define RDR1 (*(volatile char *)(0x05FFFECD)) /* Channel 1 receive data registe
r */ | |
| 1359 | |
| 1360 /* | |
| 1361 * Serial mode register bits | |
| 1362 */ | |
| 1363 | |
| 1364 #define SYNC_MODE 0x80 | |
| 1365 #define SEVEN_BIT_DATA 0x40 | |
| 1366 #define PARITY_ON 0x20 | |
| 1367 #define ODD_PARITY 0x10 | |
| 1368 #define STOP_BITS_2 0x08 | |
| 1369 #define ENABLE_MULTIP 0x04 | |
| 1370 #define PHI_64 0x03 | |
| 1371 #define PHI_16 0x02 | |
| 1372 #define PHI_4 0x01 | |
| 1373 | |
| 1374 /* | |
| 1375 * Serial control register bits | |
| 1376 */ | |
| 1377 #define SCI_TIE 0x80 /* Transmit interrupt enable */ | |
| 1378 #define SCI_RIE 0x40 /* Receive interrupt enable */ | |
| 1379 #define SCI_TE 0x20 /* Transmit enable */ | |
| 1380 #define SCI_RE 0x10 /* Receive enable */ | |
| 1381 #define SCI_MPIE 0x08 /* Multiprocessor interrupt enab
le */ | |
| 1382 #define SCI_TEIE 0x04 /* Transmit end interrupt enable
*/ | |
| 1383 #define SCI_CKE1 0x02 /* Clock enable 1 */ | |
| 1384 #define SCI_CKE0 0x01 /* Clock enable 0 */ | |
| 1385 | |
| 1386 /* | |
| 1387 * Serial status register bits | |
| 1388 */ | |
| 1389 #define SCI_TDRE 0x80 /* Transmit data register empty
*/ | |
| 1390 #define SCI_RDRF 0x40 /* Receive data register full */ | |
| 1391 #define SCI_ORER 0x20 /* Overrun error */ | |
| 1392 #define SCI_FER 0x10 /* Framing error */ | |
| 1393 #define SCI_PER 0x08 /* Parity error */ | |
| 1394 #define SCI_TEND 0x04 /* Transmit end */ | |
| 1395 #define SCI_MPB 0x02 /* Multiprocessor bit */ | |
| 1396 #define SCI_MPBT 0x01 /* Multiprocessor bit transfer *
/ | |
| 1397 | |
| 1398 | |
| 1399 /* | |
| 1400 * Port B IO Register (PBIOR) | |
| 1401 */ | |
| 1402 #define PBIOR (*(volatile char *)(0x05FFFFC6)) | |
| 1403 #define PB15IOR 0x8000 | |
| 1404 #define PB14IOR 0x4000 | |
| 1405 #define PB13IOR 0x2000 | |
| 1406 #define PB12IOR 0x1000 | |
| 1407 #define PB11IOR 0x0800 | |
| 1408 #define PB10IOR 0x0400 | |
| 1409 #define PB9IOR 0x0200 | |
| 1410 #define PB8IOR 0x0100 | |
| 1411 #define PB7IOR 0x0080 | |
| 1412 #define PB6IOR 0x0040 | |
| 1413 #define PB5IOR 0x0020 | |
| 1414 #define PB4IOR 0x0010 | |
| 1415 #define PB3IOR 0x0008 | |
| 1416 #define PB2IOR 0x0004 | |
| 1417 #define PB1IOR 0x0002 | |
| 1418 #define PB0IOR 0x0001 | |
| 1419 | |
| 1420 /* | |
| 1421 * Port B Control Register (PBCR1) | |
| 1422 */ | |
| 1423 #define PBCR1 (*(volatile short *)(0x05FFFFCC)) | |
| 1424 #define PB15MD1 0x8000 | |
| 1425 #define PB15MD0 0x4000 | |
| 1426 #define PB14MD1 0x2000 | |
| 1427 #define PB14MD0 0x1000 | |
| 1428 #define PB13MD1 0x0800 | |
| 1429 #define PB13MD0 0x0400 | |
| 1430 #define PB12MD1 0x0200 | |
| 1431 #define PB12MD0 0x0100 | |
| 1432 #define PB11MD1 0x0080 | |
| 1433 #define PB11MD0 0x0040 | |
| 1434 #define PB10MD1 0x0020 | |
| 1435 #define PB10MD0 0x0010 | |
| 1436 #define PB9MD1 0x0008 | |
| 1437 #define PB9MD0 0x0004 | |
| 1438 #define PB8MD1 0x0002 | |
| 1439 #define PB8MD0 0x0001 | |
| 1440 | |
| 1441 #define PB15MD PB15MD1|PB14MD0 | |
| 1442 #define PB14MD PB14MD1|PB14MD0 | |
| 1443 #define PB13MD PB13MD1|PB13MD0 | |
| 1444 #define PB12MD PB12MD1|PB12MD0 | |
| 1445 #define PB11MD PB11MD1|PB11MD0 | |
| 1446 #define PB10MD PB10MD1|PB10MD0 | |
| 1447 #define PB9MD PB9MD1|PB9MD0 | |
| 1448 #define PB8MD PB8MD1|PB8MD0 | |
| 1449 | |
| 1450 #define PB_TXD1 PB11MD1 | |
| 1451 #define PB_RXD1 PB10MD1 | |
| 1452 #define PB_TXD0 PB9MD1 | |
| 1453 #define PB_RXD0 PB8MD1 | |
| 1454 | |
| 1455 /* | |
| 1456 * Port B Control Register (PBCR2) | |
| 1457 */ | |
| 1458 #define PBCR2 0x05FFFFCE | |
| 1459 #define PB7MD1 0x8000 | |
| 1460 #define PB7MD0 0x4000 | |
| 1461 #define PB6MD1 0x2000 | |
| 1462 #define PB6MD0 0x1000 | |
| 1463 #define PB5MD1 0x0800 | |
| 1464 #define PB5MD0 0x0400 | |
| 1465 #define PB4MD1 0x0200 | |
| 1466 #define PB4MD0 0x0100 | |
| 1467 #define PB3MD1 0x0080 | |
| 1468 #define PB3MD0 0x0040 | |
| 1469 #define PB2MD1 0x0020 | |
| 1470 #define PB2MD0 0x0010 | |
| 1471 #define PB1MD1 0x0008 | |
| 1472 #define PB1MD0 0x0004 | |
| 1473 #define PB0MD1 0x0002 | |
| 1474 #define PB0MD0 0x0001 | |
| 1475 | |
| 1476 #define PB7MD PB7MD1|PB7MD0 | |
| 1477 #define PB6MD PB6MD1|PB6MD0 | |
| 1478 #define PB5MD PB5MD1|PB5MD0 | |
| 1479 #define PB4MD PB4MD1|PB4MD0 | |
| 1480 #define PB3MD PB3MD1|PB3MD0 | |
| 1481 #define PB2MD PB2MD1|PB2MD0 | |
| 1482 #define PB1MD PB1MD1|PB1MD0 | |
| 1483 #define PB0MD PB0MD1|PB0MD0 | |
| 1484 | |
| 1485 | |
| 1486 #ifdef MHZ | |
| 1487 #define BPS 32 * 9600 * MHZ / ( BAUD * 10) | |
| 1488 #else | |
| 1489 #define BPS 32 /* 9600 for 10 Mhz */ | |
| 1490 #endif | |
| 1491 | |
| 1492 void handleError (char theSSR); | |
| 1493 | |
| 1494 void | |
| 1495 nop (void) | |
| 1496 { | |
| 1497 | |
| 1498 } | |
| 1499 void | |
| 1500 init_serial (void) | |
| 1501 { | |
| 1502 int i; | |
| 1503 | |
| 1504 /* Clear TE and RE in Channel 1's SCR */ | |
| 1505 SCR1 &= ~(SCI_TE | SCI_RE); | |
| 1506 | |
| 1507 /* Set communication to be async, 8-bit data, no parity, 1 stop bit and use in
ternal clock */ | |
| 1508 | |
| 1509 SMR1 = 0; | |
| 1510 BRR1 = BPS; | |
| 1511 | |
| 1512 SCR1 &= ~(SCI_CKE1 | SCI_CKE0); | |
| 1513 | |
| 1514 /* let the hardware settle */ | |
| 1515 | |
| 1516 for (i = 0; i < 1000; i++) | |
| 1517 nop (); | |
| 1518 | |
| 1519 /* Turn on in and out */ | |
| 1520 SCR1 |= SCI_RE | SCI_TE; | |
| 1521 | |
| 1522 /* Set the PFC to make RXD1 (pin PB8) an input pin and TXD1 (pin PB9) an outpu
t pin */ | |
| 1523 PBCR1 &= ~(PB_TXD1 | PB_RXD1); | |
| 1524 PBCR1 |= PB_TXD1 | PB_RXD1; | |
| 1525 } | |
| 1526 | |
| 1527 | |
| 1528 int | |
| 1529 getDebugCharReady (void) | |
| 1530 { | |
| 1531 char mySSR; | |
| 1532 mySSR = SSR1 & ( SCI_PER | SCI_FER | SCI_ORER ); | |
| 1533 if ( mySSR ) | |
| 1534 handleError ( mySSR ); | |
| 1535 return SSR1 & SCI_RDRF ; | |
| 1536 } | |
| 1537 | |
| 1538 char | |
| 1539 getDebugChar (void) | |
| 1540 { | |
| 1541 char ch; | |
| 1542 char mySSR; | |
| 1543 | |
| 1544 while ( ! getDebugCharReady()) | |
| 1545 ; | |
| 1546 | |
| 1547 ch = RDR1; | |
| 1548 SSR1 &= ~SCI_RDRF; | |
| 1549 | |
| 1550 mySSR = SSR1 & (SCI_PER | SCI_FER | SCI_ORER); | |
| 1551 | |
| 1552 if (mySSR) | |
| 1553 handleError (mySSR); | |
| 1554 | |
| 1555 return ch; | |
| 1556 } | |
| 1557 | |
| 1558 int | |
| 1559 putDebugCharReady (void) | |
| 1560 { | |
| 1561 return (SSR1 & SCI_TDRE); | |
| 1562 } | |
| 1563 | |
| 1564 void | |
| 1565 putDebugChar (char ch) | |
| 1566 { | |
| 1567 while (!putDebugCharReady()) | |
| 1568 ; | |
| 1569 | |
| 1570 /* | |
| 1571 * Write data into TDR and clear TDRE | |
| 1572 */ | |
| 1573 TDR1 = ch; | |
| 1574 SSR1 &= ~SCI_TDRE; | |
| 1575 } | |
| 1576 | |
| 1577 void | |
| 1578 handleError (char theSSR) | |
| 1579 { | |
| 1580 SSR1 &= ~(SCI_ORER | SCI_PER | SCI_FER); | |
| 1581 } | |
| 1582 | |
| 1583 #endif | |
| OLD | NEW |