Annotation of sys/arch/m88k/m88k/db_sstep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: db_sstep.c,v 1.5 2006/05/03 18:12:52 miod Exp $ */
! 2: /*
! 3: * Mach Operating System
! 4: * Copyright (c) 1993-1991 Carnegie Mellon University
! 5: * Copyright (c) 1991 OMRON Corporation
! 6: * All Rights Reserved.
! 7: *
! 8: * Permission to use, copy, modify and distribute this software and its
! 9: * documentation is hereby granted, provided that both the copyright
! 10: * notice and this permission notice appear in all copies of the
! 11: * software, derivative works or modified versions, and any portions
! 12: * thereof, and that both notices appear in supporting documentation.
! 13: *
! 14: * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 15: * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
! 16: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 17: *
! 18: * Carnegie Mellon requests users of this software to return to
! 19: *
! 20: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 21: * School of Computer Science
! 22: * Carnegie Mellon University
! 23: * Pittsburgh PA 15213-3890
! 24: *
! 25: * any improvements or extensions that they make and grant Carnegie the
! 26: * rights to redistribute these changes.
! 27: */
! 28:
! 29: #include <sys/param.h>
! 30: #include <sys/systm.h>
! 31:
! 32: #include <machine/db_machdep.h>
! 33:
! 34: #include <ddb/db_access.h> /* db_get_value() */
! 35: #include <ddb/db_break.h> /* db_breakpoint_t */
! 36: #include <ddb/db_run.h>
! 37:
! 38: /*
! 39: * Support routines for software single step.
! 40: *
! 41: * Author: Daniel Stodolsky (danner@cs.cmu.edu)
! 42: *
! 43: */
! 44:
! 45: /*
! 46: * inst_load(ins)
! 47: * Returns the number of words the instruction loads. byte,
! 48: * half and word count as 1; double word as 2
! 49: */
! 50: int
! 51: inst_load(u_int ins)
! 52: {
! 53: /* look at the top six bits, for starters */
! 54: switch (ins >> (32 - 6)) {
! 55: case 0x0: /* xmem byte imm */
! 56: case 0x1: /* xmem word imm */
! 57: case 0x2: /* unsigned half-word load imm */
! 58: case 0x3: /* unsigned byte load imm */
! 59: case 0x5: /* signed word load imm */
! 60: case 0x6: /* signed half-word load imm */
! 61: case 0x7: /* signed byte load imm */
! 62: return (1);
! 63:
! 64: case 0x4: /* signed double word load imm */
! 65: return (2);
! 66:
! 67: case 0x3d: /* load/store/xmem scaled/unscaled instruction */
! 68: if ((ins & 0x0000c0e0) == 0x00000000) /* is ld/st/xmem */
! 69: /* look at bits 15-10 */
! 70: switch ((ins & 0x0000fc00) >> 10) {
! 71: case 0x0: /* xmem byte */
! 72: case 0x1: /* xmem word */
! 73: case 0x2: /* unsigned half word */
! 74: case 0x3: /* unsigned byte load */
! 75: case 0x5: /* signed word load */
! 76: case 0x6: /* signed half-word load */
! 77: case 0x7: /* signed byte load */
! 78: return (1);
! 79:
! 80: case 0x4: /* signed double word load */
! 81: return (2);
! 82: }
! 83: break;
! 84: }
! 85:
! 86: return (0);
! 87: }
! 88:
! 89: /*
! 90: * inst_store
! 91: * Like inst_load, except for store instructions.
! 92: */
! 93: int
! 94: inst_store(u_int ins)
! 95: {
! 96: /* decode top 6 bits again */
! 97: switch (ins >> (32 - 6)) {
! 98: case 0x0: /* xmem byte imm */
! 99: case 0x1: /* xmem word imm */
! 100: case 0x9: /* store word imm */
! 101: case 0xa: /* store half-word imm */
! 102: case 0xb: /* store byte imm */
! 103: return (1);
! 104:
! 105: case 0x8: /* store double word */
! 106: return (2);
! 107:
! 108: case 0x3d: /* load/store/xmem scaled/unscaled instruction */
! 109: if ((ins & 0x0000c0e0) == 0x00000000) /* is ld/st/xmem */
! 110: /* look at bits 15-10 */
! 111: switch ((ins & 0x0000fc00) >> 10) {
! 112: case 0x0: /* xmem byte imm */
! 113: case 0x1: /* xmem word imm */
! 114: case 0x9: /* store word */
! 115: case 0xa: /* store half-word */
! 116: case 0xb: /* store byte */
! 117: return (1);
! 118:
! 119: case 0x8: /* store double word */
! 120: return (2);
! 121: }
! 122: break;
! 123: }
! 124:
! 125: return (0);
! 126: }
! 127:
! 128: /*
! 129: * We can not use the MI ddb SOFTWARE_SSTEP facility, since the 88110 will use
! 130: * hardware single stepping.
! 131: * Moreover, our software single stepping implementation is tailor-made for the
! 132: * 88100 and faster than the MI code.
! 133: */
! 134:
! 135: #ifdef M88100
! 136:
! 137: boolean_t inst_branch_or_call(u_int);
! 138: db_addr_t branch_taken(u_int, db_addr_t, db_regs_t *);
! 139:
! 140: db_breakpoint_t db_not_taken_bkpt = 0;
! 141: db_breakpoint_t db_taken_bkpt = 0;
! 142:
! 143: /*
! 144: * Returns TRUE is the instruction a branch, jump or call instruction
! 145: * (br, bb0, bb1, bcnd, jmp, bsr, jsr)
! 146: */
! 147: boolean_t
! 148: inst_branch_or_call(u_int ins)
! 149: {
! 150: /* check high five bits */
! 151: switch (ins >> (32 - 5)) {
! 152: case 0x18: /* br */
! 153: case 0x19: /* bsr */
! 154: case 0x1a: /* bb0 */
! 155: case 0x1b: /* bb1 */
! 156: case 0x1d: /* bcnd */
! 157: return (TRUE);
! 158: case 0x1e: /* could be jmp or jsr */
! 159: if ((ins & 0xfffff3e0) == 0xf400c000)
! 160: return (TRUE);
! 161: }
! 162:
! 163: return (FALSE);
! 164: }
! 165:
! 166: /*
! 167: * branch_taken(instruction, program counter, regs)
! 168: *
! 169: * instruction will be a control flow instruction location at address pc.
! 170: * Branch taken is supposed to return the address to which the instruction
! 171: * would jump if the branch is taken.
! 172: */
! 173: db_addr_t
! 174: branch_taken(u_int inst, db_addr_t pc, db_regs_t *regs)
! 175: {
! 176: u_int regno;
! 177:
! 178: /*
! 179: * Quick check of the instruction. Note that we know we are only
! 180: * invoked if inst_branch_or_call() returns TRUE, so we do not
! 181: * need to repeat the jmp and jsr stricter checks here.
! 182: */
! 183: switch (inst >> (32 - 5)) {
! 184: case 0x18: /* br */
! 185: case 0x19: /* bsr */
! 186: /* signed 26 bit pc relative displacement, shift left two bits */
! 187: inst = (inst & 0x03ffffff) << 2;
! 188: /* check if sign extension is needed */
! 189: if (inst & 0x08000000)
! 190: inst |= 0xf0000000;
! 191: return (pc + inst);
! 192:
! 193: case 0x1a: /* bb0 */
! 194: case 0x1b: /* bb1 */
! 195: case 0x1d: /* bcnd */
! 196: /* signed 16 bit pc relative displacement, shift left two bits */
! 197: inst = (inst & 0x0000ffff) << 2;
! 198: /* check if sign extension is needed */
! 199: if (inst & 0x00020000)
! 200: inst |= 0xfffc0000;
! 201: return (pc + inst);
! 202:
! 203: default: /* jmp or jsr */
! 204: regno = inst & 0x1f;
! 205: return (regno == 0 ? 0 : regs->r[regno]);
! 206: }
! 207: }
! 208:
! 209: #endif /* M88100 */
! 210:
! 211: void
! 212: db_set_single_step(db_regs_t *regs)
! 213: {
! 214: #ifdef M88110
! 215: if (CPU_IS88110) {
! 216: /*
! 217: * On the 88110, we can use the hardware tracing facility...
! 218: */
! 219: regs->epsr |= PSR_TRACE | PSR_SER;
! 220: }
! 221: #endif
! 222: #ifdef M88100
! 223: if (CPU_IS88100) {
! 224: /*
! 225: * ... while the 88100 will use two breakpoints.
! 226: */
! 227: db_addr_t pc = PC_REGS(regs);
! 228: db_addr_t brpc;
! 229: u_int inst;
! 230:
! 231: /*
! 232: * User was stopped at pc, e.g. the instruction
! 233: * at pc was not executed.
! 234: */
! 235: db_read_bytes(pc, sizeof(inst), (caddr_t)&inst);
! 236:
! 237: /*
! 238: * Find if this instruction may cause a branch, and set up a
! 239: * breakpoint at the branch location.
! 240: */
! 241: if (inst_branch_or_call(inst)) {
! 242: brpc = branch_taken(inst, pc, regs);
! 243:
! 244: /* self-branches are hopeless */
! 245: if (brpc != pc && brpc != 0)
! 246: db_taken_bkpt = db_set_temp_breakpoint(brpc);
! 247: }
! 248:
! 249: db_not_taken_bkpt = db_set_temp_breakpoint(pc + 4);
! 250: }
! 251: #endif
! 252: }
! 253:
! 254: void
! 255: db_clear_single_step(regs)
! 256: db_regs_t *regs;
! 257: {
! 258: #ifdef M88110
! 259: if (CPU_IS88110) {
! 260: /* do not remove PSR_SER as we don't enable OoO */
! 261: regs->epsr &= ~PSR_TRACE;
! 262: }
! 263: #endif
! 264: #ifdef M88100
! 265: if (CPU_IS88100) {
! 266: if (db_taken_bkpt != 0) {
! 267: db_delete_temp_breakpoint(db_taken_bkpt);
! 268: db_taken_bkpt = 0;
! 269: }
! 270: if (db_not_taken_bkpt != 0) {
! 271: db_delete_temp_breakpoint(db_not_taken_bkpt);
! 272: db_not_taken_bkpt = 0;
! 273: }
! 274: }
! 275: #endif
! 276: }
CVSweb