]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/common/v2_0/src/hal_stub.c
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