TX51 pre-release
[karo-tx-redboot.git] / packages / hal / common / v2_0 / src / hal_stub.c
1 //=============================================================================
2 //
3 //      hal_stub.c
4 //
5 //      Helper functions for stub, specific to eCos HAL
6 //
7 //=============================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //=============================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):   jskov (based on powerpc/cogent hal_stub.c)
44 // Contributors:jskov, dmoseley
45 // Date:        1999-02-12
46 // Purpose:     Helper functions for stub, specific to eCos HAL
47 // Description: Parts of the GDB stub requirements are provided by
48 //              the eCos HAL, rather than target and/or board specific
49 //              code. 
50 //
51 //####DESCRIPTIONEND####
52 //
53 //=============================================================================
54
55 #include <pkgconf/hal.h>
56 #ifdef CYGPKG_CYGMON
57 #include <pkgconf/cygmon.h>
58 #endif
59
60 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
61
62 #include <cyg/hal/hal_stub.h>           // Our header
63
64 #include <cyg/hal/hal_arch.h>           // HAL_BREAKINST
65 #include <cyg/hal/hal_cache.h>          // HAL_xCACHE_x
66 #include <cyg/hal/hal_intr.h>           // interrupt disable/restore
67
68 #include <cyg/hal/hal_if.h>             // ROM calling interface
69 #include <cyg/hal/hal_misc.h>           // Helper functions
70
71 #ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT
72 #include <cyg/hal/dbg-threads-api.h>    // dbg_currthread_id
73 #endif
74
75 #ifdef USE_LONG_NAMES_FOR_ENUM_REGNAMES
76 #ifndef PC
77 #define PC REG_PC
78 #endif
79 #ifndef SP
80 #define SP REG_SP
81 #endif
82 #endif
83
84 //-----------------------------------------------------------------------------
85 // Extra eCos data.
86
87 // Some architectures use registers of different sizes, so NUMREGS
88 // alone is not suffucient to size the register save area. For those
89 // architectures, HAL_STUB_REGISTERS_SIZE is defined as the number
90 // of target_register_t sized elements in the register save area.
91 #ifndef HAL_STUB_REGISTERS_SIZE
92 #define HAL_STUB_REGISTERS_SIZE NUMREGS
93 #endif
94
95 // Saved registers.
96 HAL_SavedRegisters *_hal_registers;
97 target_register_t registers[HAL_STUB_REGISTERS_SIZE];
98 target_register_t alt_registers[HAL_STUB_REGISTERS_SIZE] ;  // Thread or saved process state
99 target_register_t * _registers = registers;                 // Pointer to current set of registers
100 #ifndef CYGPKG_REDBOOT
101 target_register_t orig_registers[HAL_STUB_REGISTERS_SIZE];  // Registers to get back to original state
102 #endif
103
104 #if defined(HAL_STUB_HW_WATCHPOINT) || defined(HAL_STUB_HW_BREAKPOINT)
105 static int  _hw_stop_reason;   // Reason we were stopped by hw.
106
107 //#define HAL_STUB_HW_SEND_STOP_REASON_TEXT
108 #ifdef CYGINT_HAL_ARM_ARCH_XSCALE
109 #define HAL_STUB_HW_SEND_STOP_REASON_TEXT
110 #endif
111
112 #ifdef HAL_STUB_HW_SEND_STOP_REASON_TEXT
113 // strings indexed by hw stop reasons defined in hal_stub.h
114
115 // Not all GDBs understand this.
116 static const char * const _hw_stop_str[] = {
117     "",
118     "hbreak",
119     "watch",
120     "rwatch",
121     "awatch"
122 };
123 #endif // HAL_STUB_HW_SEND_STOP_REASON_TEXT
124
125 static void *_watch_data_addr; // The data address if stopped by watchpoint
126 #endif // defined(HAL_STUB_HW_WATCHPOINT) || defined(HAL_STUB_HW_BREAKPOINT)
127
128 // Register validity checking
129 #ifdef CYGHWR_REGISTER_VALIDITY_CHECKING
130 int registers_valid[NUMREGS];
131 int *_registers_valid = registers_valid;
132 #endif
133
134 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this should go away
135 // Interrupt control.
136 static volatile __PFI __interruptible_control;
137 #endif
138
139 // Some architectures need extras regs reported in T packet
140 #ifndef HAL_STUB_ARCH_T_PACKET_EXTRAS
141 #define HAL_STUB_ARCH_T_PACKET_EXTRAS(x)
142 #endif
143
144 //-----------------------------------------------------------------------------
145 // Register access
146
147 #ifndef CYGARC_STUB_REGISTER_ACCESS_DEFINED
148 // Return the currently-saved value corresponding to register REG of
149 // the exception context.
150 target_register_t 
151 get_register (regnames_t reg)
152 {
153     return _registers[reg];
154 }
155 #endif
156
157 #ifdef CYGHWR_REGISTER_VALIDITY_CHECKING
158 // Return the validity of register REG.
159 int
160 get_register_valid (regnames_t reg)
161 {
162     return _registers_valid[reg];
163 }
164 #endif
165
166 #ifndef CYGARC_STUB_REGISTER_ACCESS_DEFINED
167 // Store VALUE in the register corresponding to WHICH in the exception
168 // context.
169 void 
170 put_register (regnames_t which, target_register_t value)
171 {
172 #ifdef CYGPKG_HAL_MIPS_VR4300
173     // This is a rather nasty kludge to compensate for the fact that
174     // the VR4300 GDB is rather old and does not support proper 64 bit
175     // registers. The only time this really matters is when setting
176     // the PC after loading an executable. So here we detect this case
177     // and artificially sign extend it. 
178     
179     if( which == PC && (value & 0x0000000080000000ULL ) )
180     {
181         value |= 0xFFFFFFFF00000000ULL;
182     }
183 #endif    
184     _registers[which] = value;
185 }
186 #endif // CYGARC_STUB_REGISTER_ACCESS_DEFINED
187
188 //-----------------------------------------------------------------------------
189 // Serial stuff
190 #ifdef CYGPKG_CYGMON
191 extern void ecos_bsp_console_putc(char);
192 extern char ecos_bsp_console_getc(void);
193 #endif
194
195 // Write C to the current serial port.
196 void 
197 putDebugChar (int c)
198 {
199 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
200     __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS();
201     CYGACC_COMM_IF_PUTC(*__debug_procs, c);
202 #elif defined(CYGPKG_CYGMON)
203     ecos_bsp_console_putc(c);
204 #else
205     HAL_STUB_PLATFORM_PUT_CHAR(c);
206 #endif
207 }
208
209 // Read one character from the current serial port.
210 int 
211 getDebugChar (void)
212 {
213 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
214     __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS();
215     return CYGACC_COMM_IF_GETC(*__debug_procs);
216 #elif defined(CYGPKG_CYGMON)
217     return ecos_bsp_console_getc();
218 #else
219     return HAL_STUB_PLATFORM_GET_CHAR();
220 #endif
221 }
222
223 // Flush output channel
224 void
225 hal_flush_output(void)
226 {
227 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
228     __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS();
229     CYGACC_COMM_IF_CONTROL(*__debug_procs, __COMMCTL_FLUSH_OUTPUT);
230 #endif
231 }
232
233
234 // Set the baud rate for the current serial port.
235 void 
236 __set_baud_rate (int baud) 
237 {
238 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
239     __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS();
240     CYGACC_COMM_IF_CONTROL(*__debug_procs, __COMMCTL_SETBAUD, baud);
241 #elif defined(CYGPKG_CYGMON)
242     // FIXME!
243 #else
244     HAL_STUB_PLATFORM_SET_BAUD_RATE(baud);
245 #endif
246 }
247
248 //-----------------------------------------------------------------------------
249 // GDB interrupt (BREAK) support.
250
251 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
252
253 #ifndef CYGPKG_HAL_ARM
254
255 #if (HAL_BREAKINST_SIZE == 1)
256 typedef cyg_uint8 t_inst;
257 #elif (HAL_BREAKINST_SIZE == 2)
258 typedef cyg_uint16 t_inst;
259 #elif (HAL_BREAKINST_SIZE == 4)
260 typedef cyg_uint32 t_inst;
261 #else
262 #error "Don't know how to handle that size"
263 #endif
264
265 typedef struct
266 {
267   t_inst *targetAddr;
268   t_inst savedInstr;
269 } instrBuffer;
270
271 static instrBuffer break_buffer;
272
273 volatile int cyg_hal_gdb_running_step = 0;
274
275 void 
276 cyg_hal_gdb_place_break (target_register_t pc)
277 {
278     cyg_hal_gdb_interrupt( pc ); // Let's hope this becomes a drop-through:
279 }
280
281 void 
282 cyg_hal_gdb_interrupt (target_register_t pc)
283 {
284     t_inst break_inst = HAL_BREAKINST;
285
286     CYGARC_HAL_SAVE_GP();
287
288     // Clear flag that we Continued instead of Stepping
289     cyg_hal_gdb_running_step = 0;
290     // and override existing break? So that a ^C takes effect...
291     if (NULL != break_buffer.targetAddr)
292         cyg_hal_gdb_remove_break( (target_register_t)break_buffer.targetAddr );
293
294     if (NULL == break_buffer.targetAddr) {
295         // Not always safe to read/write directly to program
296         // memory due to possibly unaligned instruction, use the
297         // provided memory functions instead.
298         __read_mem_safe(&break_buffer.savedInstr, (t_inst*)pc, HAL_BREAKINST_SIZE);
299         __write_mem_safe(&break_inst, (t_inst*)pc, HAL_BREAKINST_SIZE);
300
301         // Save the PC where we put the break, so we can remove
302         // it after the target takes the break.
303         break_buffer.targetAddr = (t_inst*)pc;
304
305         __data_cache(CACHE_FLUSH);
306         __instruction_cache(CACHE_FLUSH);
307     }
308
309     CYGARC_HAL_RESTORE_GP();
310 }
311
312 int 
313 cyg_hal_gdb_remove_break (target_register_t pc)
314 {
315     if ( cyg_hal_gdb_running_step )
316         return 0;
317
318     if ((t_inst*)pc == break_buffer.targetAddr) {
319
320         __write_mem_safe(&break_buffer.savedInstr, (t_inst*)pc, HAL_BREAKINST_SIZE);
321         break_buffer.targetAddr = NULL;
322
323         __data_cache(CACHE_FLUSH);
324         __instruction_cache(CACHE_FLUSH);
325         return 1;
326     }
327     return 0;
328 }
329
330 int 
331 cyg_hal_gdb_break_is_set (void)
332 {
333     if (NULL != break_buffer.targetAddr) {
334         return 1;
335     }
336     return 0;
337 }
338
339 #endif // CYGPKG_HAL_ARM
340
341 #endif // CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
342
343 // Use this function to disable serial interrupts whenever reply
344 // characters are expected from GDB.  The reason we want to control
345 // whether the target can be interrupted or not is simply that GDB on
346 // the host will be sending acknowledge characters/commands while the
347 // stub is running - if serial interrupts were still active, the
348 // characters would never reach the (polling) getDebugChar.
349 static void
350 interruptible(int state)
351 {
352     static int __interrupts_suspended = 0;
353
354     if (state) {
355         __interrupts_suspended--;
356         if (0 >= __interrupts_suspended) {
357             __interrupts_suspended = 0;
358 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away
359             {
360                 hal_virtual_comm_table_t* __chan;
361                 __chan = CYGACC_CALL_IF_DEBUG_PROCS();
362                 CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE);
363             }
364 #else                
365             if (__interruptible_control)
366                 __interruptible_control(1);
367 #endif
368         }
369     } else {
370         __interrupts_suspended++;
371         if (1 == __interrupts_suspended)
372 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away
373             {
374                 hal_virtual_comm_table_t* __chan;
375                 __chan = CYGACC_CALL_IF_DEBUG_PROCS();
376                 CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE);
377             }
378 #else                
379             if (__interruptible_control)
380                 __interruptible_control(0);
381 #endif
382     }
383 }
384
385 //-----------------------------------------------------------------------------
386 // eCos stub entry and exit magic.
387
388 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
389 int cyg_hal_gdb_break;
390 #endif
391
392 #ifdef CYGPKG_REDBOOT
393 // Trampoline for returning to RedBoot from exception/stub code
394 static void
395 return_from_stub(int exit_status)
396 {
397     CYGACC_CALL_IF_MONITOR_RETURN(exit_status);
398 }
399 #endif
400
401 // Called at stub *kill*
402 static void 
403 handle_exception_exit( void )
404 {
405 #ifdef CYGPKG_REDBOOT
406 #ifdef CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
407     {   // Reset the timer to default and cancel any callback
408         extern void sys_profile_reset(void);
409         sys_profile_reset();
410     }
411 #endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
412     set_pc((target_register_t)return_from_stub);
413 #else
414     int i;
415
416     for (i = 0; i < (sizeof(registers)/sizeof(registers[0])); i++)
417         registers[i] = orig_registers[i];
418 #endif
419 }
420
421 // Called at stub *entry*
422 static void 
423 handle_exception_cleanup( void )
424 {
425 #ifndef CYGPKG_REDBOOT
426     static int orig_registers_set = 0;
427 #endif
428
429     interruptible(0);
430
431     // Expand the HAL_SavedRegisters structure into the GDB register
432     // array format.
433     HAL_GET_GDB_REGISTERS(&registers[0], _hal_registers);
434     _registers = &registers[0];
435
436 #ifndef CYGPKG_REDBOOT
437     if (!orig_registers_set) {
438         int i;
439         for (i = 0; i < (sizeof(registers)/sizeof(registers[0])); i++)
440             orig_registers[i] = registers[i];
441         _registers = &orig_registers[0];
442         if (__is_breakpoint_function ())
443             __skipinst ();
444         _registers = &registers[0];
445         orig_registers_set = 1;
446     }
447 #endif
448         
449 #ifdef HAL_STUB_PLATFORM_STUBS_FIXUP
450     // Some architectures may need to fix the PC in case of a partial
451     // or fully executed trap instruction. GDB only takes correct action
452     // when the PC is pointing to the breakpoint instruction it set.
453     // 
454     // Most architectures would leave PC pointing at the trap
455     // instruction itself though, and so do not need to do anything
456     // special.
457     HAL_STUB_PLATFORM_STUBS_FIXUP();
458 #endif
459
460 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
461     // If we continued instead of stepping, when there was a break set
462     // ie. we were stepping within a critical region, clear the break, and
463     // that flag.  If we stopped for some other reason, this has no effect.
464     if ( cyg_hal_gdb_running_step ) {
465         cyg_hal_gdb_running_step = 0;
466         cyg_hal_gdb_remove_break(get_register (PC));
467     }
468
469     // FIXME: (there may be a better way to do this)
470     // If we hit a breakpoint set by the gdb interrupt stub, make it
471     // seem like an interrupt rather than having hit a breakpoint.
472     cyg_hal_gdb_break = cyg_hal_gdb_remove_break(get_register (PC));
473 #endif
474
475 #if defined(HAL_STUB_HW_WATCHPOINT) || defined(HAL_STUB_HW_BREAKPOINT)
476     // For HW watchpoint/breakpoint support, we need to know if we
477     // stopped because of watchpoint or hw break. We do that here
478     // before GDB has a chance to remove the watchpoints and save
479     // the information for later use in building response packets.
480     _hw_stop_reason = HAL_STUB_IS_STOPPED_BY_HARDWARE(_watch_data_addr);
481 #endif    
482 }
483
484 // Called at stub *exit*
485 static void 
486 handle_exception_init( void )
487 {
488     // Compact register array again.
489     HAL_SET_GDB_REGISTERS(_hal_registers, &registers[0]);
490
491     interruptible(1);
492 }
493
494
495 //-----------------------------------------------------------------------------
496 // Initialization.
497
498 // Signal handler.
499 int 
500 cyg_hal_process_signal (int signal)
501 {
502     // We don't care about the signal (atm).
503     return 0;
504 }
505
506 // Install the standard set of trap handlers for the stub.
507 void 
508 __install_traps (void)
509 {
510     // Set signal handling vector so we can treat 'C<signum>' as 'c'.
511     __process_signal_vec = &cyg_hal_process_signal;
512     __process_exit_vec = &handle_exception_exit;
513
514     __cleanup_vec = &handle_exception_cleanup;
515     __init_vec    = &handle_exception_init;
516
517 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this should go away
518 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
519     // Control of GDB interrupts.
520     __interruptible_control = HAL_STUB_PLATFORM_INTERRUPTIBLE;
521 #endif
522 #endif
523
524     // Nothing further to do, handle_exception will be called when an
525     // exception occurs.
526 }
527
528 // Initialize the hardware.
529 void 
530 initHardware (void) 
531 {
532     static int initialized = 0;
533
534     if (initialized)
535         return;
536     initialized = 1;
537
538     // Get serial port initialized.
539     HAL_STUB_PLATFORM_INIT_SERIAL();
540
541 #ifdef HAL_STUB_PLATFORM_INIT
542     // If the platform defines any initialization code, call it here.
543     HAL_STUB_PLATFORM_INIT();
544 #endif        
545
546 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this should go away
547 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
548     // Get interrupt handler initialized.
549     HAL_STUB_PLATFORM_INIT_BREAK_IRQ();
550 #endif
551 #endif // !CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
552 }
553
554 // Reset the board.
555 void 
556 __reset (void)
557 {
558 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
559     __call_if_reset_t *__rom_reset = CYGACC_CALL_IF_RESET_GET();
560     if (__rom_reset)
561         (*__rom_reset)();
562 #else
563     HAL_PLATFORM_RESET();
564 #endif
565 }
566
567 //-----------------------------------------------------------------------------
568 // Breakpoint support.
569
570 #ifndef CYGPKG_HAL_ARM
571 // This function will generate a breakpoint exception.  It is used at
572 // the beginning of a program to sync up with a debugger and can be
573 // used otherwise as a quick means to stop program execution and
574 // "break" into the debugger.
575 void
576 breakpoint()
577 {
578     HAL_BREAKPOINT(_breakinst);
579 }
580
581 // This function returns the opcode for a 'trap' instruction.
582 unsigned long 
583 __break_opcode ()
584 {
585   return HAL_BREAKINST;
586 }
587 #endif
588
589 //-----------------------------------------------------------------------------
590 // Write the 'T' packet in BUFFER. SIGVAL is the signal the program received.
591 void 
592 __build_t_packet (int sigval, char *buf)
593 {
594     target_register_t addr;
595     char *ptr = buf;
596     target_register_t extend_val = 0;
597
598     *ptr++ = 'T';
599     *ptr++ = __tohex (sigval >> 4);
600     *ptr++ = __tohex (sigval);
601
602 #ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT
603     // Include thread ID if thread manipulation is required.
604     {
605         int id = dbg_currthread_id ();
606
607         if (id != 0) {
608             *ptr++ = 't';
609             *ptr++ = 'h';
610             *ptr++ = 'r';
611             *ptr++ = 'e';
612             *ptr++ = 'a';
613             *ptr++ = 'd';
614             *ptr++ = ':';
615
616 #if (CYG_BYTEORDER == CYG_LSBFIRST)
617             // FIXME: Temporary workaround for PR 18903. Thread ID must be
618             // big-endian in the T packet.
619             {
620                 unsigned char* bep = (unsigned char*)&id;
621                 int be_id;
622
623                 be_id = id;
624                 *bep++ = (be_id >> 24) & 0xff ;
625                 *bep++ = (be_id >> 16) & 0xff ;
626                 *bep++ = (be_id >> 8) & 0xff ;
627                 *bep++ = (be_id & 0xff) ;
628             }
629 #endif
630             ptr = __mem2hex((char *)&id, ptr, sizeof(id), 0);
631             *ptr++ = ';';
632         }
633     }
634 #endif
635
636 #ifdef HAL_STUB_HW_WATCHPOINT
637     switch(_hw_stop_reason) {
638       case HAL_STUB_HW_STOP_WATCH:
639       case HAL_STUB_HW_STOP_RWATCH:
640       case HAL_STUB_HW_STOP_AWATCH:
641 #ifdef HAL_STUB_HW_SEND_STOP_REASON_TEXT
642         // Not all GDBs understand this.
643         strcpy(ptr, _hw_stop_str[_hw_stop_reason]);
644         ptr += strlen(_hw_stop_str[_hw_stop_reason]);
645 #endif
646         *ptr++ = ':';
647         // Send address MSB first
648         ptr += __intToHex(ptr, (target_register_t)_watch_data_addr,
649                           sizeof(_watch_data_addr) * 8);
650         *ptr++ = ';';
651         break;
652       default:
653         break;
654     }
655 #endif
656
657     *ptr++ = __tohex (PC >> 4);
658     *ptr++ = __tohex (PC);
659     *ptr++ = ':';
660     addr = get_register (PC);
661     if (sizeof(addr) < REGSIZE(PC))
662     {
663         // GDB is expecting REGSIZE(PC) number of bytes.
664         // We only have sizeof(addr) number.  Let's fill
665         // the appropriate number of bytes intelligently.
666 #ifdef CYGARC_SIGN_EXTEND_REGISTERS
667         {
668             unsigned long bits_in_addr = (sizeof(addr) << 3);  // ie Size in bytes * 8
669             target_register_t sign_bit_mask = (1 << (bits_in_addr - 1));
670             if ((addr & sign_bit_mask) == sign_bit_mask)
671                 extend_val = ~0;
672         }
673 #endif
674     }
675 #if (CYG_BYTEORDER == CYG_MSBFIRST)
676     ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(PC) - sizeof(addr), 0);
677 #endif
678     ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0);
679 #if (CYG_BYTEORDER == CYG_LSBFIRST)
680     ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(PC) - sizeof(addr), 0);
681 #endif
682     *ptr++ = ';';
683
684     *ptr++ = __tohex (SP >> 4);
685     *ptr++ = __tohex (SP);
686     *ptr++ = ':';
687     addr = (target_register_t) get_register (SP);
688     if (sizeof(addr) < REGSIZE(SP))
689     {
690         // GDB is expecting REGSIZE(SP) number of bytes.
691         // We only have sizeof(addr) number.  Let's fill
692         // the appropriate number of bytes intelligently.
693         extend_val = 0;
694 #ifdef CYGARC_SIGN_EXTEND_REGISTERS
695         {
696             unsigned long bits_in_addr = (sizeof(addr) << 3);  // ie Size in bytes * 8
697             target_register_t sign_bit_mask = (1 << (bits_in_addr - 1));
698             if ((addr & sign_bit_mask) == sign_bit_mask)
699                 extend_val = ~0;
700         }
701 #endif
702         ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(SP) - sizeof(addr), 0);
703     }
704     ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0);
705     *ptr++ = ';';
706
707     HAL_STUB_ARCH_T_PACKET_EXTRAS(ptr);
708     
709     *ptr++ = 0;
710 }
711
712
713 //-----------------------------------------------------------------------------
714 // Cache functions.
715
716 // Perform the specified operation on the instruction cache. 
717 // Returns 1 if the cache is enabled, 0 otherwise.
718 int 
719 __instruction_cache (cache_control_t request)
720 {
721     int state = 1;
722
723     switch (request) {
724     case CACHE_ENABLE:
725         HAL_ICACHE_ENABLE();
726         break;
727     case CACHE_DISABLE:
728         HAL_ICACHE_DISABLE();
729         state = 0;
730         break;
731     case CACHE_FLUSH:
732         HAL_ICACHE_SYNC();
733         break;
734     case CACHE_NOOP:
735         /* fall through */
736     default:
737         break;
738     }
739
740 #ifdef HAL_ICACHE_IS_ENABLED
741     HAL_ICACHE_IS_ENABLED(state);
742 #endif
743
744     return state;
745 }
746
747 // Perform the specified operation on the data cache. 
748 // Returns 1 if the cache is enabled, 0 otherwise.
749 int 
750 __data_cache (cache_control_t request)
751 {
752     int state = 1;
753
754     switch (request) {
755     case CACHE_ENABLE:
756         HAL_DCACHE_ENABLE();
757         break;
758     case CACHE_DISABLE:
759         HAL_DCACHE_DISABLE();
760         state = 0;
761         break;
762     case CACHE_FLUSH:
763         HAL_DCACHE_SYNC();
764         break;
765     case CACHE_NOOP:
766         /* fall through */
767     default:
768         break;
769     }
770 #ifdef HAL_DCACHE_IS_ENABLED
771     HAL_DCACHE_IS_ENABLED(state);
772 #endif
773
774     return state;
775 }
776
777 //-----------------------------------------------------------------------------
778 // Memory accessor functions.
779
780 // The __mem_fault_handler pointer is volatile since it is only
781 // set/cleared by the function below - which does not rely on any
782 // other functions, so the compiler may decide to not bother updating
783 // the pointer at all. If any of the memory accesses cause an
784 // exception, the pointer must be set to ensure the exception handler
785 // can make use of it.
786
787 void* volatile __mem_fault_handler = (void *)0;
788
789 /* These are the "arguments" to __do_read_mem and __do_write_mem, 
790    which are passed as globals to avoid squeezing them thru
791    __set_mem_fault_trap.  */
792
793 static volatile target_register_t memCount;
794
795 static void
796 __do_copy_mem (unsigned char* src, unsigned char* dst)
797 {
798     unsigned long *long_dst;
799     unsigned long *long_src;
800     unsigned short *short_dst;
801     unsigned short *short_src;
802
803     // Zero memCount is not really an error, but the goto is necessary to
804     // keep some compilers from reordering stuff across the 'err' label.
805     if (memCount == 0) goto err;
806
807     __mem_fault = 1;                      /* Defaults to 'fail'. Is cleared */
808                                           /* when the copy loop completes.  */
809     __mem_fault_handler = &&err;
810
811     // See if it's safe to do multi-byte, aligned operations
812     while (memCount) {
813         if ((memCount >= sizeof(long)) &&
814             (((target_register_t)dst & (sizeof(long)-1)) == 0) &&
815             (((target_register_t)src & (sizeof(long)-1)) == 0)) {
816         
817             long_dst = (unsigned long *)dst;
818             long_src = (unsigned long *)src;
819
820             *long_dst++ = *long_src++;
821             memCount -= sizeof(long);
822
823             dst = (unsigned char *)long_dst;
824             src = (unsigned char *)long_src;
825         } else if ((memCount >= sizeof(short)) &&
826                    (((target_register_t)dst & (sizeof(short)-1)) == 0) &&
827                    (((target_register_t)src & (sizeof(short)-1)) == 0)) {
828             
829             short_dst = (unsigned short *)dst;
830             short_src = (unsigned short *)src;
831
832             *short_dst++ = *short_src++;
833             memCount -= sizeof(short);
834
835             dst = (unsigned char *)short_dst;
836             src = (unsigned char *)short_src;
837         } else {
838             *dst++ = *src++;
839             memCount--;
840         }
841     }
842
843     __mem_fault = 0;
844
845  err:
846     __mem_fault_handler = (void *)0;
847 }
848
849 /*
850  * __read_mem_safe:
851  * Get contents of target memory, abort on error.
852  */
853
854 int
855 __read_mem_safe (void *dst, void *src, int count)
856 {
857   if( !CYG_HAL_STUB_PERMIT_DATA_READ( src, count ) )
858     return 0;
859
860   memCount = count;
861   __do_copy_mem((unsigned char*) src, (unsigned char*) dst);
862   return count - memCount;      // return number of bytes successfully read
863 }
864
865 /*
866  * __write_mem_safe:
867  * Set contents of target memory, abort on error.
868  */
869
870 int
871 __write_mem_safe (void *src, void *dst, int count)
872 {
873   if( !CYG_HAL_STUB_PERMIT_DATA_READ( dst, count ) )
874     return 0;
875
876   memCount = count;
877   __do_copy_mem((unsigned char*) src, (unsigned char*) dst);
878   return count - memCount;      // return number of bytes successfully written
879 }
880
881 #ifdef TARGET_HAS_HARVARD_MEMORY
882 static void
883 __do_copy_from_progmem (unsigned char* src, unsigned char* dst)
884 {
885     unsigned long *long_dst;
886     unsigned long *long_src;
887     unsigned short *short_dst;
888     unsigned short *short_src;
889
890     // Zero memCount is not really an error, but the goto is necessary to
891     // keep some compilers from reordering stuff across the 'err' label.
892     if (memCount == 0) goto err;
893
894     __mem_fault = 1;                      /* Defaults to 'fail'. Is cleared */
895                                           /* when the copy loop completes.  */
896     __mem_fault_handler = &&err;
897
898     // See if it's safe to do multi-byte, aligned operations
899     while (memCount) {
900         if ((memCount >= sizeof(long)) &&
901             (((target_register_t)dst & (sizeof(long)-1)) == 0) &&
902             (((target_register_t)src & (sizeof(long)-1)) == 0)) {
903         
904             long_dst = (unsigned long *)dst;
905             long_src = (unsigned long *)src;
906
907             *long_dst++ = __read_prog_uint32(long_src++);
908             memCount -= sizeof(long);
909
910             dst = (unsigned char *)long_dst;
911             src = (unsigned char *)long_src;
912         } else if ((memCount >= sizeof(short)) &&
913                    (((target_register_t)dst & (sizeof(short)-1)) == 0) &&
914                    (((target_register_t)src & (sizeof(short)-1)) == 0)) {
915             
916             short_dst = (unsigned short *)dst;
917             short_src = (unsigned short *)src;
918
919             *short_dst++ = __read_prog_uint16(short_src++);
920             memCount -= sizeof(short);
921
922             dst = (unsigned char *)short_dst;
923             src = (unsigned char *)short_src;
924         } else {
925             *dst++ = __read_prog_uint8(src++);
926             memCount--;
927         }
928     }
929
930     __mem_fault = 0;
931
932  err:
933     __mem_fault_handler = (void *)0;
934 }
935
936 static void
937 __do_copy_to_progmem (unsigned char* src, unsigned char* dst)
938 {
939     unsigned long *long_dst;
940     unsigned long *long_src;
941     unsigned short *short_dst;
942     unsigned short *short_src;
943
944     // Zero memCount is not really an error, but the goto is necessary to
945     // keep some compilers from reordering stuff across the 'err' label.
946     if (memCount == 0)  goto err;
947
948     __mem_fault = 1;                      /* Defaults to 'fail'. Is cleared */
949                                           /* when the copy loop completes.  */
950     __mem_fault_handler = &&err;
951
952     // See if it's safe to do multi-byte, aligned operations
953     while (memCount) {
954         if ((memCount >= sizeof(long)) &&
955             (((target_register_t)dst & (sizeof(long)-1)) == 0) &&
956             (((target_register_t)src & (sizeof(long)-1)) == 0)) {
957         
958             long_dst = (unsigned long *)dst;
959             long_src = (unsigned long *)src;
960
961             __write_prog_uint32(long_dst++, *long_src++);
962             memCount -= sizeof(long);
963
964             dst = (unsigned char *)long_dst;
965             src = (unsigned char *)long_src;
966         } else if ((memCount >= sizeof(short)) &&
967                    (((target_register_t)dst & (sizeof(short)-1)) == 0) &&
968                    (((target_register_t)src & (sizeof(short)-1)) == 0)) {
969             
970             short_dst = (unsigned short *)dst;
971             short_src = (unsigned short *)src;
972
973             __write_prog_uint16(short_dst++, *short_src++);
974             memCount -= sizeof(short);
975
976             dst = (unsigned char *)short_dst;
977             src = (unsigned char *)short_src;
978         } else {
979             __write_prog_uint8(dst++, *src++);
980             memCount--;
981         }
982     }
983
984     __mem_fault = 0;
985
986  err:
987     __mem_fault_handler = (void *)0;
988 }
989
990 /*
991  * __read_progmem_safe:
992  * Get contents of target memory, abort on error.
993  */
994
995 int
996 __read_progmem_safe (void *dst, void *src, int count)
997 {
998   if( !CYG_HAL_STUB_PERMIT_CODE_READ( src, count ) )
999     return 0;
1000
1001   memCount = count;
1002   __do_copy_from_progmem((unsigned char*) src, (unsigned char*) dst);
1003   return count - memCount;      // return number of bytes successfully read
1004 }
1005
1006 /*
1007  * __write_progmem_safe:
1008  * Set contents of target memory, abort on error.
1009  */
1010
1011 int
1012 __write_progmem_safe (void *src, void *dst, int count)
1013 {
1014   if( !CYG_HAL_STUB_PERMIT_CODE_WRITE( dst, count ) )
1015     return 0;
1016
1017   memCount = count;
1018   __do_copy_to_progmem((unsigned char*) src, (unsigned char*) dst);
1019   return count - memCount;      // return number of bytes successfully written
1020 }
1021 #endif
1022
1023 //-----------------------------------------------------------------------------
1024 // Target extras?!
1025 int 
1026 __process_target_query(char * pkt, char * out, int maxOut)
1027 { return 0 ; }
1028 int 
1029 __process_target_set(char * pkt, char * out, int maxout)
1030 { return 0 ; }
1031 int 
1032 __process_target_packet(char * pkt, char * out, int maxout)
1033 { return 0 ; }
1034
1035 // GDB string output, making sure interrupts are disabled.
1036 // This function gets used by some diag output functions.
1037 void 
1038 hal_output_gdb_string(target_register_t str, int string_len)
1039 {
1040     unsigned long __state;
1041     HAL_DISABLE_INTERRUPTS(__state);
1042     __output_gdb_string(str, string_len);
1043     HAL_RESTORE_INTERRUPTS(__state);
1044 }
1045
1046 #endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS