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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [mips/] [arch/] [v2_0/] [src/] [mips-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
//      mips-stub.h
4
//
5
//      Helper functions for stub, generic to all MIPS processors
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):     Red Hat, nickg
44
// Contributors:  Red Hat, nickg
45
// Date:          1998-06-08
46
// Purpose:       
47
// Description:   Helper functions for stub, generic to all MIPS processors
48
// Usage:         
49
//
50
//####DESCRIPTIONEND####
51
//
52
//========================================================================
53
 
54
#include <stddef.h>
55
 
56
#include <pkgconf/hal.h>
57
 
58
#ifdef CYGPKG_REDBOOT
59
#include <pkgconf/redboot.h>
60
#endif
61
 
62
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
63
 
64
#include <cyg/hal/hal_stub.h>
65
 
66
#define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS
67
#include <cyg/hal/mips-regs.h>
68
 
69
#include <cyg/hal/hal_arch.h>
70
#include <cyg/hal/hal_intr.h>
71
#include <cyg/hal/mips_opcode.h>
72
 
73
typedef unsigned long t_inst;
74
 
75
/*----------------------------------------------------------------------
76
 * Asynchronous interrupt support
77
 */
78
 
79
static struct
80
{
81
  t_inst *targetAddr;
82
  t_inst savedInstr;
83
} asyncBuffer;
84
 
85
/* Called to asynchronously interrupt a running program.
86
   Must be passed address of instruction interrupted.
87
   This is typically called in response to a debug port
88
   receive interrupt.
89
*/
90
 
91
void
92
install_async_breakpoint(void *epc)
93
{
94
  long gp_save;
95
 
96
  /* This may be called from a separately linked program,
97
     so we need to save and restore the incoming gp register
98
     and setup our stub local gp register.
99
     Alternatively, we could skip this foolishness if we
100
     compiled libstub with "-G 0". */
101
 
102
  __asm__ volatile ( "move   %0,$28\n"
103
                     ".extern _gp\n"
104
                     "la     $28,_gp\n"
105
                     : "=r" (gp_save) );
106
 
107
  asyncBuffer.targetAddr = epc;
108
  asyncBuffer.savedInstr = *(t_inst *)epc;
109
  *(t_inst *)epc = *(t_inst *)_breakinst;
110
  __instruction_cache(CACHE_FLUSH);
111
  __data_cache(CACHE_FLUSH);
112
 
113
  __asm__  volatile ( "move   $28,%0\n" :: "r"(gp_save) );
114
}
115
 
116
/*--------------------------------------------------------------------*/
117
/* Given a trap value TRAP, return the corresponding signal. */
118
 
119
int __computeSignal (unsigned int trap_number)
120
{
121
  switch (trap_number)
122
    {
123
    case EXC_INT:
124
      /* External interrupt */
125
      return SIGINT;
126
 
127
    case EXC_RI:
128
      /* Reserved instruction */
129
    case EXC_CPU:
130
      /* Coprocessor unusable */
131
      return SIGILL;
132
 
133
    case EXC_BP:
134
      /* Break point */
135
      if (asyncBuffer.targetAddr != NULL)
136
        {
137
          /* BP installed by serial driver to stop running program */
138
          *asyncBuffer.targetAddr = asyncBuffer.savedInstr;
139
          __instruction_cache(CACHE_FLUSH);
140
          __data_cache(CACHE_FLUSH);
141
          asyncBuffer.targetAddr = NULL;
142
          return SIGINT;
143
        }
144
      return SIGTRAP;
145
 
146
    case EXC_OVF:
147
      /* Arithmetic overflow */
148
    case EXC_TRAP:
149
      /* Trap exception */
150
    case EXC_FPE:
151
      /* Floating Point Exception */
152
      return SIGFPE;
153
 
154
    case EXC_IBE:
155
      /* Bus error (Ifetch) */
156
    case EXC_DBE:
157
      /* Bus error (data load or store) */
158
      return SIGBUS;
159
 
160
    case EXC_MOD:
161
      /* TLB modification exception */
162
    case EXC_TLBL:
163
      /* TLB miss (Load or Ifetch) */
164
    case EXC_TLBS:
165
      /* TLB miss (Store) */
166
    case EXC_ADEL:
167
      /* Address error (Load or Ifetch) */
168
    case EXC_ADES:
169
      /* Address error (Store) */
170
      return SIGSEGV;
171
 
172
    case EXC_SYS:
173
      /* System call */
174
      return SIGSYS;
175
 
176
    default:
177
      return SIGTERM;
178
    }
179
}
180
 
181
/* Return the trap number corresponding to the last-taken trap. */
182
 
183
int __get_trap_number (void)
184
{
185
  return (get_register (CAUSE) & CAUSE_EXCMASK) >> CAUSE_EXCSHIFT;
186
}
187
 
188
#if defined(CYGSEM_REDBOOT_BSP_SYSCALLS)
189
int __is_bsp_syscall(void)
190
{
191
    return __get_trap_number() == EXC_SYS;
192
}
193
#endif
194
 
195
/* Set the currently-saved pc register value to PC. This also updates NPC
196
   as needed. */
197
 
198
void set_pc (target_register_t pc)
199
{
200
  put_register (PC, pc);
201
}
202
 
203
 
204
/*----------------------------------------------------------------------
205
 * Single-step support
206
 */
207
 
208
/* Saved instruction data for single step support.  */
209
 
210
static struct
211
{
212
  t_inst *targetAddr;
213
  t_inst savedInstr;
214
} instrBuffer;
215
 
216
 
217
/* Set things up so that the next user resume will execute one instruction.
218
   This may be done by setting breakpoints or setting a single step flag
219
   in the saved user registers, for example. */
220
 
221
void __single_step (void)
222
{
223
  InstFmt inst;
224
  t_inst *pc = (t_inst *) get_register (PC);
225
 
226
  instrBuffer.targetAddr = pc + 1;              /* set default */
227
 
228
  inst.word = *pc;                              /* read the next instruction  */
229
 
230
//diag_printf("pc %08x %08x\n",pc,inst.word);
231
 
232
  switch (inst.RType.op) {                    /* override default if branch */
233
    case OP_SPECIAL:
234
      switch (inst.RType.func) {
235
        case OP_JR:
236
        case OP_JALR:
237
          instrBuffer.targetAddr = (t_inst *) get_register (inst.RType.rs);
238
          break;
239
      };
240
      break;
241
 
242
    case OP_REGIMM:
243
      switch (inst.IType.rt) {
244
        case OP_BLTZ:
245
        case OP_BLTZL:
246
        case OP_BLTZAL:
247
        case OP_BLTZALL:
248
            if ((int)get_register (inst.IType.rs) < 0 )
249
            instrBuffer.targetAddr =
250
              (t_inst *)(((signed short)inst.IType.imm<<2)
251
                                        + (get_register (PC) + 4));
252
          else
253
            instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
254
          break;
255
        case OP_BGEZ:
256
        case OP_BGEZL:
257
        case OP_BGEZAL:
258
        case OP_BGEZALL:
259
            if ((int)get_register (inst.IType.rs) >= 0 )
260
            instrBuffer.targetAddr =
261
              (t_inst *)(((signed short)inst.IType.imm<<2)
262
                                        + (get_register (PC) + 4));
263
          else
264
            instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
265
          break;
266
      };
267
      break;
268
 
269
    case OP_J:
270
    case OP_JAL:
271
      instrBuffer.targetAddr =
272
        (t_inst *)((inst.JType.target<<2)
273
                   + ((get_register (PC) + 4)&0xf0000000));
274
      break;
275
 
276
    case OP_BEQ:
277
    case OP_BEQL:
278
      if (get_register (inst.IType.rs) == get_register (inst.IType.rt))
279
        instrBuffer.targetAddr =
280
          (t_inst *)(((signed short)inst.IType.imm<<2)
281
                     + (get_register (PC) + 4));
282
      else
283
        instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
284
      break;
285
    case OP_BNE:
286
    case OP_BNEL:
287
      if (get_register (inst.IType.rs) != get_register (inst.IType.rt))
288
        instrBuffer.targetAddr =
289
          (t_inst *)(((signed short)inst.IType.imm<<2)
290
                     + (get_register (PC) + 4));
291
      else
292
        instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
293
      break;
294
    case OP_BLEZ:
295
    case OP_BLEZL:
296
        if ((int)get_register (inst.IType.rs) <= 0)
297
        instrBuffer.targetAddr =
298
          (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4));
299
      else
300
        instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
301
      break;
302
    case OP_BGTZ:
303
    case OP_BGTZL:
304
        if ((int)get_register (inst.IType.rs) > 0)
305
        instrBuffer.targetAddr =
306
          (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4));
307
      else
308
        instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
309
      break;
310
 
311
#ifdef CYGHWR_HAL_MIPS_FPU
312
 
313
    case OP_COP1:
314
      if (inst.RType.rs == OP_BC)
315
          switch (inst.RType.rt) {
316
            case COPz_BCF:
317
            case COPz_BCFL:
318
                if (get_register (FCR31) & FCR31_C)
319
                instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
320
              else
321
                instrBuffer.targetAddr =
322
                  (t_inst *)(((signed short)inst.IType.imm<<2)
323
                                            + (get_register (PC) + 4));
324
              break;
325
            case COPz_BCT:
326
            case COPz_BCTL:
327
                if (get_register (FCR31) & FCR31_C)
328
                instrBuffer.targetAddr =
329
                  (t_inst *)(((signed short)inst.IType.imm<<2)
330
                                            + (get_register (PC) + 4));
331
              else
332
                instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8);
333
              break;
334
          };
335
      break;
336
#endif
337
 
338
  }
339
}
340
 
341
 
342
/* Clear the single-step state. */
343
 
344
void __clear_single_step (void)
345
{
346
//diag_printf("clear_ss ta %08x\n",instrBuffer.targetAddr);
347
  if (instrBuffer.targetAddr != NULL)
348
    {
349
      *instrBuffer.targetAddr = instrBuffer.savedInstr;
350
      instrBuffer.targetAddr = NULL;
351
    }
352
  instrBuffer.savedInstr = NOP_INSTR;
353
}
354
 
355
 
356
void __install_breakpoints ()
357
{
358
//diag_printf("install_bpt ta %08x\n",instrBuffer.targetAddr);
359
  if (instrBuffer.targetAddr != NULL)
360
    {
361
      instrBuffer.savedInstr = *instrBuffer.targetAddr;
362
      *instrBuffer.targetAddr = __break_opcode ();
363
//diag_printf("ta %08x si %08x *ta %08x\n",
364
//            instrBuffer.targetAddr,instrBuffer.savedInstr,*instrBuffer.targetAddr);
365
 
366
      /* Ensure that the planted breakpoint makes it out to memory and
367
         is subsequently loaded into the instruction cache.
368
      */
369
      __data_cache (CACHE_FLUSH) ;
370
      __instruction_cache (CACHE_FLUSH) ;
371
    }
372
 
373
  /* Install the breakpoints in the breakpoint list */
374
  __install_breakpoint_list();
375
}
376
 
377
void __clear_breakpoints (void)
378
{
379
  __clear_breakpoint_list();
380
}
381
 
382
 
383
/* If the breakpoint we hit is in the breakpoint() instruction, return a
384
   non-zero value. */
385
 
386
int
387
__is_breakpoint_function ()
388
{
389
    return get_register (PC) == (target_register_t)(unsigned long)&_breakinst;
390
}
391
 
392
 
393
/* Skip the current instruction.  Since this is only called by the
394
   stub when the PC points to a breakpoint or trap instruction,
395
   we can safely just skip 4. */
396
 
397
void __skipinst (void)
398
{
399
    put_register (PC, get_register (PC) + 4);
400
}
401
 
402
#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.