[BACK]Return to db_sstep.c CVS log [TXT][DIR] Up to [local] / sys / arch / m88k / m88k

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