OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [common/] [current/] [src/] [hal_stub.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.