Mercurial > ecos-v2_0-branch
comparison packages/hal/mips/arch/current/src/mips-stub.c @ 0:3111d98ba7b3 ecos-v1_1-release
Initial commit of eCos version 1.1
| author | jlarmour |
|---|---|
| date | Tue, 11 May 1999 11:16:07 +0000 |
| parents | |
| children | 443894e2e912 |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:3111d98ba7b3 |
|---|---|
| 1 /* mips-stub.c - helper functions for stub, generic to all MIPS processors | |
| 2 * | |
| 3 * Copyright (c) 1998 Cygnus Support | |
| 4 * | |
| 5 * The authors hereby grant permission to use, copy, modify, distribute, | |
| 6 * and license this software and its documentation for any purpose, provided | |
| 7 * that existing copyright notices are retained in all copies and that this | |
| 8 * notice is included verbatim in any distributions. No written agreement, | |
| 9 * license, or royalty fee is required for any of the authorized uses. | |
| 10 * Modifications to this software may be copyrighted by their authors | |
| 11 * and need not follow the licensing terms described here, provided that | |
| 12 * the new terms are clearly indicated on the first page of each file where | |
| 13 * they apply. | |
| 14 */ | |
| 15 | |
| 16 #include <stddef.h> | |
| 17 | |
| 18 #include "cyg/hal/hal_stub.h" | |
| 19 | |
| 20 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS | |
| 21 | |
| 22 #include "cyg/hal/hal_arch.h" | |
| 23 #include <cyg/hal/mips-regs.h> | |
| 24 #include <cyg/hal/mips_opcode.h> | |
| 25 | |
| 26 #define SIGHUP 1 /* hangup */ | |
| 27 #define SIGINT 2 /* interrupt */ | |
| 28 #define SIGQUIT 3 /* quit */ | |
| 29 #define SIGILL 4 /* illegal instruction (not reset when caught) */ | |
| 30 #define SIGTRAP 5 /* trace trap (not reset when caught) */ | |
| 31 #define SIGIOT 6 /* IOT instruction */ | |
| 32 #define SIGABRT 6 /* used by abort, replace SIGIOT in the future */ | |
| 33 #define SIGEMT 7 /* EMT instruction */ | |
| 34 #define SIGFPE 8 /* floating point exception */ | |
| 35 #define SIGKILL 9 /* kill (cannot be caught or ignored) */ | |
| 36 #define SIGBUS 10 /* bus error */ | |
| 37 #define SIGSEGV 11 /* segmentation violation */ | |
| 38 #define SIGSYS 12 /* bad argument to system call */ | |
| 39 #define SIGPIPE 13 /* write on a pipe with no one to read it */ | |
| 40 #define SIGALRM 14 /* alarm clock */ | |
| 41 #define SIGTERM 15 /* software termination signal from kill */ | |
| 42 | |
| 43 | |
| 44 /* Saved registers. */ | |
| 45 | |
| 46 HAL_SavedRegisters *_hal_registers; | |
| 47 | |
| 48 target_register_t * _registers; /* A pointer to the current set of registers */ | |
| 49 target_register_t registers[NUMREGS]; | |
| 50 target_register_t alt_registers[NUMREGS] ; /* Thread or saved process state */ | |
| 51 | |
| 52 | |
| 53 /* Given a trap value TRAP, return the corresponding signal. */ | |
| 54 | |
| 55 int __computeSignal (unsigned int trap_number) | |
| 56 { | |
| 57 switch (trap_number) | |
| 58 { | |
| 59 case EXC_INT: | |
| 60 /* External interrupt */ | |
| 61 return SIGINT; | |
| 62 | |
| 63 case EXC_RI: | |
| 64 /* Reserved instruction */ | |
| 65 case EXC_CPU: | |
| 66 /* Coprocessor unusable */ | |
| 67 return SIGILL; | |
| 68 | |
| 69 case EXC_BP: | |
| 70 /* Break point */ | |
| 71 return SIGTRAP; | |
| 72 | |
| 73 case EXC_OVF: | |
| 74 /* Arithmetic overflow */ | |
| 75 case EXC_TRAP: | |
| 76 /* Trap exception */ | |
| 77 case EXC_FPE: | |
| 78 /* Floating Point Exception */ | |
| 79 return SIGFPE; | |
| 80 | |
| 81 case EXC_IBE: | |
| 82 /* Bus error (Ifetch) */ | |
| 83 case EXC_DBE: | |
| 84 /* Bus error (data load or store) */ | |
| 85 return SIGBUS; | |
| 86 | |
| 87 case EXC_MOD: | |
| 88 /* TLB modification exception */ | |
| 89 case EXC_TLBL: | |
| 90 /* TLB miss (Load or Ifetch) */ | |
| 91 case EXC_TLBS: | |
| 92 /* TLB miss (Store) */ | |
| 93 case EXC_ADEL: | |
| 94 /* Address error (Load or Ifetch) */ | |
| 95 case EXC_ADES: | |
| 96 /* Address error (Store) */ | |
| 97 return SIGSEGV; | |
| 98 | |
| 99 case EXC_SYS: | |
| 100 /* System call */ | |
| 101 return SIGSYS; | |
| 102 | |
| 103 default: | |
| 104 return SIGTERM; | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 | |
| 109 /* Return the trap number corresponding to the last-taken trap. */ | |
| 110 | |
| 111 int __get_trap_number (void) | |
| 112 { | |
| 113 return (get_register (CAUSE) & CAUSE_EXCMASK) >> CAUSE_EXCSHIFT; | |
| 114 } | |
| 115 | |
| 116 // Return the currently-saved value corresponding to register REG of | |
| 117 // the exception context. | |
| 118 target_register_t get_register (regnames_t reg) | |
| 119 { | |
| 120 return registers[reg]; | |
| 121 } | |
| 122 | |
| 123 // Store VALUE in the register corresponding to WHICH in the exception | |
| 124 // context. | |
| 125 void put_register (regnames_t which, target_register_t value) | |
| 126 { | |
| 127 registers[which] = value; | |
| 128 } | |
| 129 | |
| 130 | |
| 131 /* Set the currently-saved pc register value to PC. This also updates NPC | |
| 132 as needed. */ | |
| 133 | |
| 134 void set_pc (target_register_t pc) | |
| 135 { | |
| 136 put_register (PC, pc); | |
| 137 } | |
| 138 | |
| 139 | |
| 140 /*---------------------------------------------------------------------- | |
| 141 * Single-step support | |
| 142 */ | |
| 143 | |
| 144 /* Saved instruction data for single step support. */ | |
| 145 | |
| 146 typedef unsigned long t_inst; | |
| 147 | |
| 148 static struct | |
| 149 { | |
| 150 t_inst *targetAddr; | |
| 151 t_inst savedInstr; | |
| 152 } instrBuffer; | |
| 153 | |
| 154 | |
| 155 /* Set things up so that the next user resume will execute one instruction. | |
| 156 This may be done by setting breakpoints or setting a single step flag | |
| 157 in the saved user registers, for example. */ | |
| 158 | |
| 159 void single_step (void) | |
| 160 { | |
| 161 InstFmt inst; | |
| 162 t_inst *pc = (t_inst *) get_register (PC); | |
| 163 | |
| 164 instrBuffer.targetAddr = pc + 1; /* set default */ | |
| 165 | |
| 166 inst.word = *pc; /* read the next instruction */ | |
| 167 | |
| 168 //diag_printf("pc %08x %08x\n",pc,inst.word); | |
| 169 | |
| 170 switch (inst.RType.op) { /* override default if branch */ | |
| 171 case OP_SPECIAL: | |
| 172 switch (inst.RType.func) { | |
| 173 case OP_JR: | |
| 174 case OP_JALR: | |
| 175 instrBuffer.targetAddr = (t_inst *) get_register (inst.RType.rs); | |
| 176 break; | |
| 177 }; | |
| 178 break; | |
| 179 | |
| 180 case OP_REGIMM: | |
| 181 switch (inst.IType.rt) { | |
| 182 case OP_BLTZ: | |
| 183 case OP_BLTZL: | |
| 184 case OP_BLTZAL: | |
| 185 case OP_BLTZALL: | |
| 186 if (get_register (inst.IType.rs) < 0 ) | |
| 187 instrBuffer.targetAddr = | |
| 188 (t_inst *)(((signed short)inst.IType.imm<<2) | |
| 189 + (get_register (PC) + 4)); | |
| 190 else | |
| 191 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); | |
| 192 break; | |
| 193 case OP_BGEZ: | |
| 194 case OP_BGEZL: | |
| 195 case OP_BGEZAL: | |
| 196 case OP_BGEZALL: | |
| 197 if (get_register (inst.IType.rs) >= 0 ) | |
| 198 instrBuffer.targetAddr = | |
| 199 (t_inst *)(((signed short)inst.IType.imm<<2) | |
| 200 + (get_register (PC) + 4)); | |
| 201 else | |
| 202 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); | |
| 203 break; | |
| 204 }; | |
| 205 break; | |
| 206 | |
| 207 case OP_J: | |
| 208 case OP_JAL: | |
| 209 instrBuffer.targetAddr = | |
| 210 (t_inst *)((inst.JType.target<<2) | |
| 211 + ((get_register (PC) + 4)&0xf0000000)); | |
| 212 break; | |
| 213 | |
| 214 case OP_BEQ: | |
| 215 case OP_BEQL: | |
| 216 if (get_register (inst.IType.rs) == get_register (inst.IType.rt)) | |
| 217 instrBuffer.targetAddr = | |
| 218 (t_inst *)(((signed short)inst.IType.imm<<2) | |
| 219 + (get_register (PC) + 4)); | |
| 220 else | |
| 221 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); | |
| 222 break; | |
| 223 case OP_BNE: | |
| 224 case OP_BNEL: | |
| 225 if (get_register (inst.IType.rs) != get_register (inst.IType.rt)) | |
| 226 instrBuffer.targetAddr = | |
| 227 (t_inst *)(((signed short)inst.IType.imm<<2) | |
| 228 + (get_register (PC) + 4)); | |
| 229 else | |
| 230 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); | |
| 231 break; | |
| 232 case OP_BLEZ: | |
| 233 case OP_BLEZL: | |
| 234 if (get_register (inst.IType.rs) <= 0) | |
| 235 instrBuffer.targetAddr = | |
| 236 (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4)); | |
| 237 else | |
| 238 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); | |
| 239 break; | |
| 240 case OP_BGTZ: | |
| 241 case OP_BGTZL: | |
| 242 if (get_register (inst.IType.rs) > 0) | |
| 243 instrBuffer.targetAddr = | |
| 244 (t_inst *)(((signed short)inst.IType.imm<<2) + (get_register (PC) + 4)); | |
| 245 else | |
| 246 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); | |
| 247 break; | |
| 248 | |
| 249 #if 0 /* no floating point support at the moment */ | |
| 250 case OP_COP1: | |
| 251 if (inst.RType.rs == OP_BC) | |
| 252 switch (inst.RType.rt) { | |
| 253 case COPz_BCF: | |
| 254 case COPz_BCFL: | |
| 255 if (get_register (FCSR) & CSR_C) | |
| 256 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); | |
| 257 else | |
| 258 instrBuffer.targetAddr = | |
| 259 (t_inst *)(((signed short)inst.IType.imm<<2) | |
| 260 + (get_register (PC) + 4)); | |
| 261 break; | |
| 262 case COPz_BCT: | |
| 263 case COPz_BCTL: | |
| 264 if (get_register (FCSR) & CSR_C) | |
| 265 instrBuffer.targetAddr = | |
| 266 (t_inst *)(((signed short)inst.IType.imm<<2) | |
| 267 + (get_register (PC) + 4)); | |
| 268 else | |
| 269 instrBuffer.targetAddr = (t_inst *)(get_register (PC) + 8); | |
| 270 break; | |
| 271 }; | |
| 272 break; | |
| 273 #endif | |
| 274 | |
| 275 } | |
| 276 } | |
| 277 | |
| 278 | |
| 279 /* Clear the single-step state. */ | |
| 280 | |
| 281 void clear_single_step (void) | |
| 282 { | |
| 283 //diag_printf("clear_ss ta %08x\n",instrBuffer.targetAddr); | |
| 284 if (instrBuffer.targetAddr != NULL) | |
| 285 { | |
| 286 *instrBuffer.targetAddr = instrBuffer.savedInstr; | |
| 287 instrBuffer.targetAddr = NULL; | |
| 288 } | |
| 289 instrBuffer.savedInstr = NOP_INSTR; | |
| 290 } | |
| 291 | |
| 292 | |
| 293 void install_breakpoints () | |
| 294 { | |
| 295 //diag_printf("install_bpt ta %08x\n",instrBuffer.targetAddr); | |
| 296 if (instrBuffer.targetAddr != NULL) | |
| 297 { | |
| 298 instrBuffer.savedInstr = *instrBuffer.targetAddr; | |
| 299 *instrBuffer.targetAddr = __break_opcode (); | |
| 300 //diag_printf("ta %08x si %08x *ta %08x\n", | |
| 301 // instrBuffer.targetAddr,instrBuffer.savedInstr,*instrBuffer.targetAddr); | |
| 302 } | |
| 303 } | |
| 304 | |
| 305 | |
| 306 /* If the breakpoint we hit is in the breakpoint() instruction, return a | |
| 307 non-zero value. */ | |
| 308 | |
| 309 int | |
| 310 __is_breakpoint_function () | |
| 311 { | |
| 312 return get_register (PC) == (target_register_t)&_breakinst; | |
| 313 } | |
| 314 | |
| 315 | |
| 316 /* Skip the current instruction. Since this is only called by the | |
| 317 stub when the PC points to a breakpoint or trap instruction, | |
| 318 we can safely just skip 4. */ | |
| 319 | |
| 320 void __skipinst (void) | |
| 321 { | |
| 322 put_register (PC, get_register (PC) + 4); | |
| 323 } | |
| 324 | |
| 325 | |
| 326 /* Write the 'T' packet in BUFFER. SIGVAL is the signal the program | |
| 327 received. */ | |
| 328 | |
| 329 void __build_t_packet (int sigval, char *buf) | |
| 330 { | |
| 331 target_register_t addr; | |
| 332 char *ptr = buf; | |
| 333 target_register_t *sp; | |
| 334 | |
| 335 sp = (target_register_t *) get_register (SP); | |
| 336 | |
| 337 *ptr++ = 'T'; | |
| 338 *ptr++ = __tohex (sigval >> 4); | |
| 339 *ptr++ = __tohex (sigval); | |
| 340 | |
| 341 | |
| 342 #ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT | |
| 343 // Include thread ID if thread manipulation is required. | |
| 344 { | |
| 345 int id; | |
| 346 extern int dbg_currthread_id(void); // FIXME: get from header instead | |
| 347 | |
| 348 *ptr++ = 't'; | |
| 349 *ptr++ = 'h'; | |
| 350 *ptr++ = 'r'; | |
| 351 *ptr++ = 'e'; | |
| 352 *ptr++ = 'a'; | |
| 353 *ptr++ = 'd'; | |
| 354 *ptr++ = ':'; | |
| 355 | |
| 356 id = dbg_currthread_id (); | |
| 357 ptr = __mem2hex((char *)&id, ptr, sizeof(id), 0); | |
| 358 *ptr++ = ';'; | |
| 359 } | |
| 360 #endif | |
| 361 | |
| 362 *ptr++ = __tohex (PC >> 4); | |
| 363 *ptr++ = __tohex (PC); | |
| 364 *ptr++ = ':'; | |
| 365 addr = get_register (PC); | |
| 366 ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0); | |
| 367 *ptr++ = ';'; | |
| 368 | |
| 369 *ptr++ = __tohex (SP >> 4); | |
| 370 *ptr++ = __tohex (SP); | |
| 371 *ptr++ = ':'; | |
| 372 ptr = __mem2hex((char *)&sp, ptr, sizeof(sp), 0); | |
| 373 *ptr++ = ';'; | |
| 374 | |
| 375 *ptr++ = 0; | |
| 376 } | |
| 377 | |
| 378 #endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS |
