[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

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