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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [common/] [v2_0/] [src/] [hal_stub.c] - Blame information for rev 802

Go to most recent revision | Details | Compare with Previous | View Log

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