1 //=============================================================================
5 // Helper functions for stub, specific to eCos HAL
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.
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.
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
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.
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.
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.
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####
43 // Author(s): jskov (based on powerpc/cogent hal_stub.c)
44 // Contributors:jskov, dmoseley
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
51 //####DESCRIPTIONEND####
53 //=============================================================================
55 #include <pkgconf/hal.h>
57 #include <pkgconf/cygmon.h>
60 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
62 #include <cyg/hal/hal_stub.h> // Our header
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
68 #include <cyg/hal/hal_if.h> // ROM calling interface
69 #include <cyg/hal/hal_misc.h> // Helper functions
71 #ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT
72 #include <cyg/hal/dbg-threads-api.h> // dbg_currthread_id
75 #ifdef USE_LONG_NAMES_FOR_ENUM_REGNAMES
84 //-----------------------------------------------------------------------------
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
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
104 #if defined(HAL_STUB_HW_WATCHPOINT) || defined(HAL_STUB_HW_BREAKPOINT)
105 static int _hw_stop_reason; // Reason we were stopped by hw.
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
112 #ifdef HAL_STUB_HW_SEND_STOP_REASON_TEXT
113 // strings indexed by hw stop reasons defined in hal_stub.h
115 // Not all GDBs understand this.
116 static const char * const _hw_stop_str[] = {
123 #endif // HAL_STUB_HW_SEND_STOP_REASON_TEXT
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)
128 // Register validity checking
129 #ifdef CYGHWR_REGISTER_VALIDITY_CHECKING
130 int registers_valid[NUMREGS];
131 int *_registers_valid = registers_valid;
134 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this should go away
135 // Interrupt control.
136 static volatile __PFI __interruptible_control;
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)
144 //-----------------------------------------------------------------------------
147 #ifndef CYGARC_STUB_REGISTER_ACCESS_DEFINED
148 // Return the currently-saved value corresponding to register REG of
149 // the exception context.
151 get_register (regnames_t reg)
153 return _registers[reg];
157 #ifdef CYGHWR_REGISTER_VALIDITY_CHECKING
158 // Return the validity of register REG.
160 get_register_valid (regnames_t reg)
162 return _registers_valid[reg];
166 #ifndef CYGARC_STUB_REGISTER_ACCESS_DEFINED
167 // Store VALUE in the register corresponding to WHICH in the exception
170 put_register (regnames_t which, target_register_t value)
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.
179 if( which == PC && (value & 0x0000000080000000ULL ) )
181 value |= 0xFFFFFFFF00000000ULL;
184 _registers[which] = value;
186 #endif // CYGARC_STUB_REGISTER_ACCESS_DEFINED
188 //-----------------------------------------------------------------------------
191 extern void ecos_bsp_console_putc(char);
192 extern char ecos_bsp_console_getc(void);
195 // Write C to the current serial port.
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);
205 HAL_STUB_PLATFORM_PUT_CHAR(c);
209 // Read one character from the current serial port.
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();
219 return HAL_STUB_PLATFORM_GET_CHAR();
223 // Flush output channel
225 hal_flush_output(void)
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);
234 // Set the baud rate for the current serial port.
236 __set_baud_rate (int baud)
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)
244 HAL_STUB_PLATFORM_SET_BAUD_RATE(baud);
248 //-----------------------------------------------------------------------------
249 // GDB interrupt (BREAK) support.
251 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
253 #ifndef CYGPKG_HAL_ARM
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;
262 #error "Don't know how to handle that size"
271 static instrBuffer break_buffer;
273 volatile int cyg_hal_gdb_running_step = 0;
276 cyg_hal_gdb_place_break (target_register_t pc)
278 cyg_hal_gdb_interrupt( pc ); // Let's hope this becomes a drop-through:
282 cyg_hal_gdb_interrupt (target_register_t pc)
284 t_inst break_inst = HAL_BREAKINST;
286 CYGARC_HAL_SAVE_GP();
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 );
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);
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;
305 __data_cache(CACHE_FLUSH);
306 __instruction_cache(CACHE_FLUSH);
309 CYGARC_HAL_RESTORE_GP();
313 cyg_hal_gdb_remove_break (target_register_t pc)
315 if ( cyg_hal_gdb_running_step )
318 if ((t_inst*)pc == break_buffer.targetAddr) {
320 __write_mem_safe(&break_buffer.savedInstr, (t_inst*)pc, HAL_BREAKINST_SIZE);
321 break_buffer.targetAddr = NULL;
323 __data_cache(CACHE_FLUSH);
324 __instruction_cache(CACHE_FLUSH);
331 cyg_hal_gdb_break_is_set (void)
333 if (NULL != break_buffer.targetAddr) {
339 #endif // CYGPKG_HAL_ARM
341 #endif // CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
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.
350 interruptible(int state)
352 static int __interrupts_suspended = 0;
355 __interrupts_suspended--;
356 if (0 >= __interrupts_suspended) {
357 __interrupts_suspended = 0;
358 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away
360 hal_virtual_comm_table_t* __chan;
361 __chan = CYGACC_CALL_IF_DEBUG_PROCS();
362 CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE);
365 if (__interruptible_control)
366 __interruptible_control(1);
370 __interrupts_suspended++;
371 if (1 == __interrupts_suspended)
372 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away
374 hal_virtual_comm_table_t* __chan;
375 __chan = CYGACC_CALL_IF_DEBUG_PROCS();
376 CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE);
379 if (__interruptible_control)
380 __interruptible_control(0);
385 //-----------------------------------------------------------------------------
386 // eCos stub entry and exit magic.
388 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
389 int cyg_hal_gdb_break;
392 #ifdef CYGPKG_REDBOOT
393 // Trampoline for returning to RedBoot from exception/stub code
395 return_from_stub(int exit_status)
397 CYGACC_CALL_IF_MONITOR_RETURN(exit_status);
401 // Called at stub *kill*
403 handle_exception_exit( void )
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);
411 #endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF
412 set_pc((target_register_t)return_from_stub);
416 for (i = 0; i < (sizeof(registers)/sizeof(registers[0])); i++)
417 registers[i] = orig_registers[i];
421 // Called at stub *entry*
423 handle_exception_cleanup( void )
425 #ifndef CYGPKG_REDBOOT
426 static int orig_registers_set = 0;
431 // Expand the HAL_SavedRegisters structure into the GDB register
433 HAL_GET_GDB_REGISTERS(®isters[0], _hal_registers);
434 _registers = ®isters[0];
436 #ifndef CYGPKG_REDBOOT
437 if (!orig_registers_set) {
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 ())
444 _registers = ®isters[0];
445 orig_registers_set = 1;
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.
454 // Most architectures would leave PC pointing at the trap
455 // instruction itself though, and so do not need to do anything
457 HAL_STUB_PLATFORM_STUBS_FIXUP();
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));
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));
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);
484 // Called at stub *exit*
486 handle_exception_init( void )
488 // Compact register array again.
489 HAL_SET_GDB_REGISTERS(_hal_registers, ®isters[0]);
495 //-----------------------------------------------------------------------------
500 cyg_hal_process_signal (int signal)
502 // We don't care about the signal (atm).
506 // Install the standard set of trap handlers for the stub.
508 __install_traps (void)
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;
514 __cleanup_vec = &handle_exception_cleanup;
515 __init_vec = &handle_exception_init;
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;
524 // Nothing further to do, handle_exception will be called when an
528 // Initialize the hardware.
532 static int initialized = 0;
538 // Get serial port initialized.
539 HAL_STUB_PLATFORM_INIT_SERIAL();
541 #ifdef HAL_STUB_PLATFORM_INIT
542 // If the platform defines any initialization code, call it here.
543 HAL_STUB_PLATFORM_INIT();
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();
551 #endif // !CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
558 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
559 __call_if_reset_t *__rom_reset = CYGACC_CALL_IF_RESET_GET();
563 HAL_PLATFORM_RESET();
567 //-----------------------------------------------------------------------------
568 // Breakpoint support.
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.
578 HAL_BREAKPOINT(_breakinst);
581 // This function returns the opcode for a 'trap' instruction.
585 return HAL_BREAKINST;
589 //-----------------------------------------------------------------------------
590 // Write the 'T' packet in BUFFER. SIGVAL is the signal the program received.
592 __build_t_packet (int sigval, char *buf)
594 target_register_t addr;
596 target_register_t extend_val = 0;
599 *ptr++ = __tohex (sigval >> 4);
600 *ptr++ = __tohex (sigval);
602 #ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT
603 // Include thread ID if thread manipulation is required.
605 int id = dbg_currthread_id ();
616 #if (CYG_BYTEORDER == CYG_LSBFIRST)
617 // FIXME: Temporary workaround for PR 18903. Thread ID must be
618 // big-endian in the T packet.
620 unsigned char* bep = (unsigned char*)&id;
624 *bep++ = (be_id >> 24) & 0xff ;
625 *bep++ = (be_id >> 16) & 0xff ;
626 *bep++ = (be_id >> 8) & 0xff ;
627 *bep++ = (be_id & 0xff) ;
630 ptr = __mem2hex((char *)&id, ptr, sizeof(id), 0);
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]);
647 // Send address MSB first
648 ptr += __intToHex(ptr, (target_register_t)_watch_data_addr,
649 sizeof(_watch_data_addr) * 8);
657 *ptr++ = __tohex (PC >> 4);
658 *ptr++ = __tohex (PC);
660 addr = get_register (PC);
661 if (sizeof(addr) < REGSIZE(PC))
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
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)
675 #if (CYG_BYTEORDER == CYG_MSBFIRST)
676 ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(PC) - sizeof(addr), 0);
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);
684 *ptr++ = __tohex (SP >> 4);
685 *ptr++ = __tohex (SP);
687 addr = (target_register_t) get_register (SP);
688 if (sizeof(addr) < REGSIZE(SP))
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.
694 #ifdef CYGARC_SIGN_EXTEND_REGISTERS
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)
702 ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(SP) - sizeof(addr), 0);
704 ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0);
707 HAL_STUB_ARCH_T_PACKET_EXTRAS(ptr);
713 //-----------------------------------------------------------------------------
716 // Perform the specified operation on the instruction cache.
717 // Returns 1 if the cache is enabled, 0 otherwise.
719 __instruction_cache (cache_control_t request)
728 HAL_ICACHE_DISABLE();
740 #ifdef HAL_ICACHE_IS_ENABLED
741 HAL_ICACHE_IS_ENABLED(state);
747 // Perform the specified operation on the data cache.
748 // Returns 1 if the cache is enabled, 0 otherwise.
750 __data_cache (cache_control_t request)
759 HAL_DCACHE_DISABLE();
770 #ifdef HAL_DCACHE_IS_ENABLED
771 HAL_DCACHE_IS_ENABLED(state);
777 //-----------------------------------------------------------------------------
778 // Memory accessor functions.
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.
787 void* volatile __mem_fault_handler = (void *)0;
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. */
793 static volatile target_register_t memCount;
796 __do_copy_mem (unsigned char* src, unsigned char* dst)
798 unsigned long *long_dst;
799 unsigned long *long_src;
800 unsigned short *short_dst;
801 unsigned short *short_src;
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;
807 __mem_fault = 1; /* Defaults to 'fail'. Is cleared */
808 /* when the copy loop completes. */
809 __mem_fault_handler = &&err;
811 // See if it's safe to do multi-byte, aligned operations
813 if ((memCount >= sizeof(long)) &&
814 (((target_register_t)dst & (sizeof(long)-1)) == 0) &&
815 (((target_register_t)src & (sizeof(long)-1)) == 0)) {
817 long_dst = (unsigned long *)dst;
818 long_src = (unsigned long *)src;
820 *long_dst++ = *long_src++;
821 memCount -= sizeof(long);
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)) {
829 short_dst = (unsigned short *)dst;
830 short_src = (unsigned short *)src;
832 *short_dst++ = *short_src++;
833 memCount -= sizeof(short);
835 dst = (unsigned char *)short_dst;
836 src = (unsigned char *)short_src;
846 __mem_fault_handler = (void *)0;
851 * Get contents of target memory, abort on error.
855 __read_mem_safe (void *dst, void *src, int count)
857 if( !CYG_HAL_STUB_PERMIT_DATA_READ( src, count ) )
861 __do_copy_mem((unsigned char*) src, (unsigned char*) dst);
862 return count - memCount; // return number of bytes successfully read
867 * Set contents of target memory, abort on error.
871 __write_mem_safe (void *src, void *dst, int count)
873 if( !CYG_HAL_STUB_PERMIT_DATA_READ( dst, count ) )
877 __do_copy_mem((unsigned char*) src, (unsigned char*) dst);
878 return count - memCount; // return number of bytes successfully written
881 #ifdef TARGET_HAS_HARVARD_MEMORY
883 __do_copy_from_progmem (unsigned char* src, unsigned char* dst)
885 unsigned long *long_dst;
886 unsigned long *long_src;
887 unsigned short *short_dst;
888 unsigned short *short_src;
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;
894 __mem_fault = 1; /* Defaults to 'fail'. Is cleared */
895 /* when the copy loop completes. */
896 __mem_fault_handler = &&err;
898 // See if it's safe to do multi-byte, aligned operations
900 if ((memCount >= sizeof(long)) &&
901 (((target_register_t)dst & (sizeof(long)-1)) == 0) &&
902 (((target_register_t)src & (sizeof(long)-1)) == 0)) {
904 long_dst = (unsigned long *)dst;
905 long_src = (unsigned long *)src;
907 *long_dst++ = __read_prog_uint32(long_src++);
908 memCount -= sizeof(long);
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)) {
916 short_dst = (unsigned short *)dst;
917 short_src = (unsigned short *)src;
919 *short_dst++ = __read_prog_uint16(short_src++);
920 memCount -= sizeof(short);
922 dst = (unsigned char *)short_dst;
923 src = (unsigned char *)short_src;
925 *dst++ = __read_prog_uint8(src++);
933 __mem_fault_handler = (void *)0;
937 __do_copy_to_progmem (unsigned char* src, unsigned char* dst)
939 unsigned long *long_dst;
940 unsigned long *long_src;
941 unsigned short *short_dst;
942 unsigned short *short_src;
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;
948 __mem_fault = 1; /* Defaults to 'fail'. Is cleared */
949 /* when the copy loop completes. */
950 __mem_fault_handler = &&err;
952 // See if it's safe to do multi-byte, aligned operations
954 if ((memCount >= sizeof(long)) &&
955 (((target_register_t)dst & (sizeof(long)-1)) == 0) &&
956 (((target_register_t)src & (sizeof(long)-1)) == 0)) {
958 long_dst = (unsigned long *)dst;
959 long_src = (unsigned long *)src;
961 __write_prog_uint32(long_dst++, *long_src++);
962 memCount -= sizeof(long);
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)) {
970 short_dst = (unsigned short *)dst;
971 short_src = (unsigned short *)src;
973 __write_prog_uint16(short_dst++, *short_src++);
974 memCount -= sizeof(short);
976 dst = (unsigned char *)short_dst;
977 src = (unsigned char *)short_src;
979 __write_prog_uint8(dst++, *src++);
987 __mem_fault_handler = (void *)0;
991 * __read_progmem_safe:
992 * Get contents of target memory, abort on error.
996 __read_progmem_safe (void *dst, void *src, int count)
998 if( !CYG_HAL_STUB_PERMIT_CODE_READ( src, count ) )
1002 __do_copy_from_progmem((unsigned char*) src, (unsigned char*) dst);
1003 return count - memCount; // return number of bytes successfully read
1007 * __write_progmem_safe:
1008 * Set contents of target memory, abort on error.
1012 __write_progmem_safe (void *src, void *dst, int count)
1014 if( !CYG_HAL_STUB_PERMIT_CODE_WRITE( dst, count ) )
1018 __do_copy_to_progmem((unsigned char*) src, (unsigned char*) dst);
1019 return count - memCount; // return number of bytes successfully written
1023 //-----------------------------------------------------------------------------
1026 __process_target_query(char * pkt, char * out, int maxOut)
1029 __process_target_set(char * pkt, char * out, int maxout)
1032 __process_target_packet(char * pkt, char * out, int maxout)
1035 // GDB string output, making sure interrupts are disabled.
1036 // This function gets used by some diag output functions.
1038 hal_output_gdb_string(target_register_t str, int string_len)
1040 unsigned long __state;
1041 HAL_DISABLE_INTERRUPTS(__state);
1042 __output_gdb_string(str, string_len);
1043 HAL_RESTORE_INTERRUPTS(__state);
1046 #endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS