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

Annotation of sys/arch/sparc64/sparc64/emul.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: emul.c,v 1.12 2003/11/03 07:01:33 david Exp $ */
        !             2: /*     $NetBSD: emul.c,v 1.8 2001/06/29 23:58:40 eeh Exp $     */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1997, 2001 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Christos Zoulas.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *        This product includes software developed by the NetBSD
        !            22:  *        Foundation, Inc. and its contributors.
        !            23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            24:  *    contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            37:  * POSSIBILITY OF SUCH DAMAGE.
        !            38:  */
        !            39:
        !            40: #include <sys/param.h>
        !            41: #include <sys/systm.h>
        !            42: #include <sys/proc.h>
        !            43: #include <sys/signalvar.h>
        !            44: #include <sys/malloc.h>
        !            45: #include <machine/reg.h>
        !            46: #include <machine/instr.h>
        !            47: #include <machine/cpu.h>
        !            48: #include <machine/psl.h>
        !            49: #include <sparc64/sparc64/cpuvar.h>
        !            50: #include <uvm/uvm_extern.h>
        !            51:
        !            52: #ifdef DEBUG_EMUL
        !            53: # define DPRINTF(a) printf a
        !            54: #else
        !            55: # define DPRINTF(a)
        !            56: #endif
        !            57:
        !            58: #define GPR(tf, i)     ((int32_t *)(u_long)&tf->tf_global)[i]
        !            59: #define IPR(tf, i)     ((int32_t *)(u_long)tf->tf_out[6])[i - 16]
        !            60: #define FPR(p, i)      ((int32_t) p->p_md.md_fpstate->fs_regs[i])
        !            61:
        !            62: static __inline int readgpreg(struct trapframe64 *, int, void *);
        !            63: static __inline int readfpreg(struct proc *, int, void *);
        !            64: static __inline int writegpreg(struct trapframe64 *, int, const void *);
        !            65: static __inline int writefpreg(struct proc *, int, const void *);
        !            66: static __inline int decodeaddr(struct trapframe64 *, union instr *, void *);
        !            67: static int muldiv(struct trapframe64 *, union instr *, int32_t *, int32_t *,
        !            68:     int32_t *);
        !            69: void swap_quad(int64_t *);
        !            70:
        !            71: #define        REGNAME(i)      "goli"[i >> 3], i & 7
        !            72:
        !            73:
        !            74: static __inline int
        !            75: readgpreg(tf, i, val)
        !            76:        struct trapframe64 *tf;
        !            77:        int i;
        !            78:        void *val;
        !            79: {
        !            80:        int error = 0;
        !            81:        if (i == 0)
        !            82:                *(int32_t *) val = 0;
        !            83:        else if (i < 16)
        !            84:                *(int32_t *) val = GPR(tf, i);
        !            85:        else
        !            86:                error = copyin(&IPR(tf, i), val, sizeof(int32_t));
        !            87:
        !            88:        return error;
        !            89: }
        !            90:
        !            91:
        !            92: static __inline int
        !            93: writegpreg(tf, i, val)
        !            94:        struct trapframe64 *tf;
        !            95:        int i;
        !            96:        const void *val;
        !            97: {
        !            98:        int error = 0;
        !            99:
        !           100:        if (i == 0)
        !           101:                return error;
        !           102:        else if (i < 16)
        !           103:                GPR(tf, i) = *(int32_t *) val;
        !           104:        else
        !           105:                /* XXX: Fix copyout prototype */
        !           106:                error = copyout((caddr_t) val, &IPR(tf, i), sizeof(int32_t));
        !           107:
        !           108:        return error;
        !           109: }
        !           110:
        !           111:
        !           112: static __inline int
        !           113: readfpreg(p, i, val)
        !           114:        struct proc *p;
        !           115:        int i;
        !           116:        void *val;
        !           117: {
        !           118:        *(int32_t *) val = FPR(p, i);
        !           119:        return 0;
        !           120: }
        !           121:
        !           122:
        !           123: static __inline int
        !           124: writefpreg(p, i, val)
        !           125:        struct proc *p;
        !           126:        int i;
        !           127:        const void *val;
        !           128: {
        !           129:        FPR(p, i) = *(const int32_t *) val;
        !           130:        return 0;
        !           131: }
        !           132:
        !           133: static __inline int
        !           134: decodeaddr(tf, code, val)
        !           135:        struct trapframe64 *tf;
        !           136:        union instr *code;
        !           137:        void *val;
        !           138: {
        !           139:        if (code->i_simm13.i_i)
        !           140:                *((int32_t *) val) = code->i_simm13.i_simm13;
        !           141:        else {
        !           142:                int error;
        !           143:
        !           144:                if (code->i_asi.i_asi)
        !           145:                        return EINVAL;
        !           146:                if ((error = readgpreg(tf, code->i_asi.i_rs2, val)) != 0)
        !           147:                        return error;
        !           148:        }
        !           149:        return 0;
        !           150: }
        !           151:
        !           152:
        !           153: static int
        !           154: muldiv(tf, code, rd, rs1, rs2)
        !           155:        struct trapframe64 *tf;
        !           156:        union instr *code;
        !           157:        int32_t *rd, *rs1, *rs2;
        !           158: {
        !           159:        /*
        !           160:         * We check for {S,U}{MUL,DIV}{,cc}
        !           161:         *
        !           162:         * [c = condition code, s = sign]
        !           163:         * Mul = 0c101s
        !           164:         * Div = 0c111s
        !           165:         */
        !           166:        union {
        !           167:                struct {
        !           168:                        unsigned unused:26;     /* padding */
        !           169:                        unsigned zero:1;        /* zero by opcode */
        !           170:                        unsigned cc:1;          /* one to send condition code */
        !           171:                        unsigned one1:1;        /* one by opcode */
        !           172:                        unsigned div:1;         /* one if divide */
        !           173:                        unsigned one2:1;        /* one by opcode */
        !           174:                        unsigned sgn:1;         /* sign bit */
        !           175:                } bits;
        !           176:                int num;
        !           177:        } op;
        !           178:
        !           179:        op.num = code->i_op3.i_op3;
        !           180:
        !           181: #ifdef DEBUG_EMUL
        !           182:        printf("muldiv 0x%x: %c%s%s %c%d, %c%d, ", code->i_int,
        !           183:            "us"[op.bits.sgn], op.bits.div ? "div" : "mul",
        !           184:            op.bits.cc ? "cc" : "", REGNAME(code->i_op3.i_rd),
        !           185:            REGNAME(code->i_op3.i_rs1));
        !           186:        if (code->i_loadstore.i_i)
        !           187:                printf("0x%x\n", *rs2);
        !           188:        else
        !           189:                printf("%c%d\n", REGNAME(code->i_asi.i_rs2));
        !           190: #endif
        !           191:
        !           192:        if (op.bits.div) {
        !           193:                if (*rs2 == 0) {
        !           194:                        /*
        !           195:                         * XXX: to be 100% correct here, on sunos we need to
        !           196:                         *      ignore the error and return *rd = *rs1.
        !           197:                         *      It should be easy to fix by passing struct
        !           198:                         *      proc in here.
        !           199:                         */
        !           200:                        DPRINTF(("muldiv: avoid zerodivide\n"));
        !           201:                        return EINVAL;
        !           202:                }
        !           203:                *rd = *rs1 / *rs2;
        !           204:                DPRINTF(("muldiv: %d / %d = %d\n", *rs1, *rs2, *rd));
        !           205:        }
        !           206:        else {
        !           207:                *rd = *rs1 * *rs2;
        !           208:                DPRINTF(("muldiv: %d * %d = %d\n", *rs1, *rs2, *rd));
        !           209:        }
        !           210:
        !           211:        if (op.bits.cc) {
        !           212:                /* Set condition codes */
        !           213:                tf->tf_tstate &= ~(TSTATE_CCR);
        !           214:
        !           215:                if (*rd == 0)
        !           216:                        tf->tf_tstate |= (u_int64_t)(ICC_Z|XCC_Z) << TSTATE_CCR_SHIFT;
        !           217:                else {
        !           218:                        if (op.bits.sgn && *rd < 0)
        !           219:                                tf->tf_tstate |= (u_int64_t)(ICC_N|XCC_N) << TSTATE_CCR_SHIFT;
        !           220:                        if (op.bits.div) {
        !           221:                                if (*rd * *rs2 != *rs1)
        !           222:                                        tf->tf_tstate |= (u_int64_t)(ICC_V|XCC_V) << TSTATE_CCR_SHIFT;
        !           223:                        }
        !           224:                        else {
        !           225:                                if (*rd / *rs2 != *rs1)
        !           226:                                        tf->tf_tstate |= (u_int64_t)(ICC_V|XCC_V) << TSTATE_CCR_SHIFT;
        !           227:                        }
        !           228:                }
        !           229:        }
        !           230:
        !           231:        return 0;
        !           232: }
        !           233:
        !           234: /*
        !           235:  * Code to handle alignment faults on the sparc. This is enabled by sending
        !           236:  * a fixalign trap. Such code is generated by compiling with cc -misalign
        !           237:  * on SunOS, but we don't have such a feature yet on our gcc.
        !           238:  */
        !           239:
        !           240: int
        !           241: fixalign(p, tf)
        !           242:        struct proc *p;
        !           243:        struct trapframe64 *tf;
        !           244: {
        !           245:        static u_char sizedef[] = { 0x4, 0xff, 0x2, 0x8 };
        !           246:
        !           247:        /*
        !           248:         * This is particular to load and store instructions
        !           249:         */
        !           250:        union {
        !           251:                struct {
        !           252:                        unsigned unused:26;     /* 26 padding */
        !           253:                        unsigned fl:1;          /* 1 bit float flag */
        !           254:                        unsigned op:1;          /* 1 bit opcode */
        !           255:                        unsigned sgn:1;         /* 1 bit sign */
        !           256:                        unsigned st:1;          /* 1 bit load/store */
        !           257:                        unsigned sz:2;          /* 2 bit size register */
        !           258:                } bits;
        !           259:                int num;
        !           260:        } op;
        !           261:
        !           262:        union {
        !           263:                double  d;
        !           264:                int32_t i[2];
        !           265:                int16_t s[4];
        !           266:                int8_t  c[8];
        !           267:        } data;
        !           268:
        !           269:        union instr code;
        !           270:        size_t size;
        !           271:        int64_t rs1, rs2;
        !           272:        int error;
        !           273:
        !           274:        /* fetch and check the instruction that caused the fault */
        !           275:        error = copyin((caddr_t)(u_long)tf->tf_pc, &code.i_int, sizeof(code.i_int));
        !           276:        if (error != 0) {
        !           277:                DPRINTF(("fixalign: Bad instruction fetch\n"));
        !           278:                return EINVAL;
        !           279:        }
        !           280:
        !           281:        /* Only support format 3 */
        !           282:        if (code.i_any.i_op != 3) {
        !           283:                DPRINTF(("fixalign: Not a load or store\n"));
        !           284:                return EINVAL;
        !           285:        }
        !           286:
        !           287:        op.num = code.i_loadstore.i_op3;
        !           288:
        !           289:        /* Check operand size */
        !           290:        if ((size = sizedef[op.bits.sz]) == 0xff) {
        !           291:                DPRINTF(("fixalign: Bad operand size\n"));
        !           292:                return EINVAL;
        !           293:        }
        !           294:
        !           295:        write_user_windows();
        !           296:
        !           297:        if ((error = readgpreg(tf, code.i_op3.i_rs1, &rs1)) != 0) {
        !           298:                DPRINTF(("fixalign: read rs1 %d\n", error));
        !           299:                return error;
        !           300:        }
        !           301:
        !           302:        if ((error = decodeaddr(tf, &code, &rs2)) != 0) {
        !           303:                DPRINTF(("fixalign: decode addr %d\n", error));
        !           304:                return error;
        !           305:        }
        !           306:
        !           307:
        !           308:        rs1 += rs2;
        !           309:
        !           310: #ifdef DEBUG_EMUL
        !           311:        printf("memalign 0x%x: %s%c%c %c%d, %c%d, ", code.i_int,
        !           312:            op.bits.st ? "st" : "ld", "us"[op.bits.sgn],
        !           313:            "w*hd"[op.bits.sz], op.bits.fl ? 'f' : REGNAME(code.i_op3.i_rd),
        !           314:            REGNAME(code.i_op3.i_rs1));
        !           315:        if (code.i_loadstore.i_i)
        !           316:                printf("0x%llx\n", (unsigned long long)rs2);
        !           317:        else
        !           318:                printf("%c%d\n", REGNAME(code.i_asi.i_rs2));
        !           319: #endif
        !           320: #ifdef DIAGNOSTIC
        !           321:        if (op.bits.fl && p != fpproc)
        !           322:                panic("fp align without being the FP owning process");
        !           323: #endif
        !           324:
        !           325:        if (op.bits.st) {
        !           326:                if (op.bits.fl) {
        !           327:                        if (p == fpproc) {
        !           328:                                savefpstate(p->p_md.md_fpstate);
        !           329:                                fpproc = NULL;
        !           330:                        }
        !           331:
        !           332:                        error = readfpreg(p, code.i_op3.i_rd, &data.i[0]);
        !           333:                        if (error)
        !           334:                                return error;
        !           335:                        if (size == 8) {
        !           336:                                error = readfpreg(p, code.i_op3.i_rd + 1,
        !           337:                                    &data.i[1]);
        !           338:                                if (error)
        !           339:                                        return error;
        !           340:                        }
        !           341:                }
        !           342:                else {
        !           343:                        error = readgpreg(tf, code.i_op3.i_rd, &data.i[0]);
        !           344:                        if (error)
        !           345:                                return error;
        !           346:                        if (size == 8) {
        !           347:                                error = readgpreg(tf, code.i_op3.i_rd + 1,
        !           348:                                    &data.i[1]);
        !           349:                                if (error)
        !           350:                                        return error;
        !           351:                        }
        !           352:                }
        !           353:
        !           354:                if (size == 2)
        !           355:                        return copyout(&data.s[1], (caddr_t)(u_long)rs1, size);
        !           356:                else
        !           357:                        return copyout(&data.d, (caddr_t)(u_long)rs1, size);
        !           358:        }
        !           359:        else { /* load */
        !           360:                if (size == 2) {
        !           361:                        error = copyin((caddr_t)(u_long)rs1, &data.s[1], size);
        !           362:                        if (error)
        !           363:                                return error;
        !           364:
        !           365:                        /* Sign extend if necessary */
        !           366:                        if (op.bits.sgn && (data.s[1] & 0x8000) != 0)
        !           367:                                data.s[0] = ~0;
        !           368:                        else
        !           369:                                data.s[0] = 0;
        !           370:                }
        !           371:                else
        !           372:                        error = copyin((caddr_t)(u_long)rs1, &data.d, size);
        !           373:
        !           374:                if (error)
        !           375:                        return error;
        !           376:
        !           377:                if (op.bits.fl) {
        !           378:                        error = writefpreg(p, code.i_op3.i_rd, &data.i[0]);
        !           379:                        if (error)
        !           380:                                return error;
        !           381:                        if (size == 8) {
        !           382:                                error = writefpreg(p, code.i_op3.i_rd + 1,
        !           383:                                    &data.i[1]);
        !           384:                                if (error)
        !           385:                                        return error;
        !           386:                        }
        !           387:                        loadfpstate(p->p_md.md_fpstate);
        !           388:                        fpproc = p;
        !           389:                }
        !           390:                else {
        !           391:                        error = writegpreg(tf, code.i_op3.i_rd, &data.i[0]);
        !           392:                        if (error)
        !           393:                                return error;
        !           394:                        if (size == 8)
        !           395:                                error = writegpreg(tf, code.i_op3.i_rd + 1,
        !           396:                                    &data.i[1]);
        !           397:                }
        !           398:        }
        !           399:        return error;
        !           400: }
        !           401:
        !           402: /*
        !           403:  * Emulate unimplemented instructions on earlier sparc chips.
        !           404:  */
        !           405: int
        !           406: emulinstr(pc, tf)
        !           407:        vaddr_t pc;
        !           408:        struct trapframe64 *tf;
        !           409: {
        !           410:        union instr code;
        !           411:        int32_t rs1, rs2, rd;
        !           412:        int error;
        !           413:
        !           414:        /* fetch and check the instruction that caused the fault */
        !           415:        error = copyin((caddr_t) pc, &code.i_int, sizeof(code.i_int));
        !           416:        if (error != 0) {
        !           417:                DPRINTF(("emulinstr: Bad instruction fetch\n"));
        !           418:                return (SIGILL);
        !           419:        }
        !           420:
        !           421:        /* Only support format 2 */
        !           422:        if (code.i_any.i_op != 2) {
        !           423:                DPRINTF(("emulinstr: Not a format 2 instruction\n"));
        !           424:                return (SIGILL);
        !           425:        }
        !           426:
        !           427:        write_user_windows();
        !           428:
        !           429:        if ((error = readgpreg(tf, code.i_op3.i_rs1, &rs1)) != 0) {
        !           430:                DPRINTF(("emulinstr: read rs1 %d\n", error));
        !           431:                return (SIGILL);
        !           432:        }
        !           433:
        !           434:        if ((error = decodeaddr(tf, &code, &rs2)) != 0) {
        !           435:                DPRINTF(("emulinstr: decode addr %d\n", error));
        !           436:                return (SIGILL);
        !           437:        }
        !           438:
        !           439:        switch (code.i_op3.i_op3) {
        !           440:        case IOP3_FLUSH:
        !           441: /*             cpuinfo.cache_flush((caddr_t)(rs1 + rs2), 4); XXX */
        !           442:                return (0);
        !           443:
        !           444:        default:
        !           445:                if ((code.i_op3.i_op3 & 0x2a) != 0xa) {
        !           446:                        DPRINTF(("emulinstr: Unsupported op3 0x%x\n",
        !           447:                            code.i_op3.i_op3));
        !           448:                        return (SIGILL);
        !           449:                }
        !           450:                else if ((error = muldiv(tf, &code, &rd, &rs1, &rs2)) != 0)
        !           451:                        return (SIGFPE);
        !           452:        }
        !           453:
        !           454:        if ((error = writegpreg(tf, code.i_op3.i_rd, &rd)) != 0) {
        !           455:                DPRINTF(("muldiv: write rd %d\n", error));
        !           456:                return (SIGILL);
        !           457:        }
        !           458:
        !           459:        return (0);
        !           460: }
        !           461:
        !           462: #define        SIGN_EXT13(v)   (((int64_t)(v) << 51) >> 51)
        !           463:
        !           464: void
        !           465: swap_quad(int64_t *p)
        !           466: {
        !           467:        int64_t t;
        !           468:
        !           469:        t = htole64(p[0]);
        !           470:        p[0] = htole64(p[1]);
        !           471:        p[1] = t;
        !           472: }
        !           473:
        !           474: /*
        !           475:  * emulate STQF, STQFA, LDQF, and LDQFA
        !           476:  */
        !           477: int
        !           478: emul_qf(int32_t insv, struct proc *p, union sigval sv, struct trapframe *tf)
        !           479: {
        !           480:        extern struct fpstate64 initfpstate;
        !           481:        struct fpstate64 *fs = p->p_md.md_fpstate;
        !           482:        int64_t addr, buf[2];
        !           483:        union instr ins;
        !           484:        int freg, isload, err;
        !           485:        u_int8_t asi;
        !           486:
        !           487:        ins.i_int = insv;
        !           488:        freg = ins.i_op3.i_rd & ~1;
        !           489:        freg |= (ins.i_op3.i_rd & 1) << 5;
        !           490:
        !           491:        if (ins.i_op3.i_op3 == IOP3_LDQF || ins.i_op3.i_op3 == IOP3_LDQFA)
        !           492:                isload = 1;
        !           493:        else
        !           494:                isload = 0;
        !           495:
        !           496:        if (ins.i_op3.i_op3 == IOP3_STQF || ins.i_op3.i_op3 == IOP3_LDQF)
        !           497:                asi = ASI_PRIMARY;
        !           498:        else if (ins.i_loadstore.i_i)
        !           499:                asi = (tf->tf_tstate & TSTATE_ASI) >> TSTATE_ASI_SHIFT;
        !           500:        else
        !           501:                asi = ins.i_asi.i_asi;
        !           502:
        !           503:        addr = tf->tf_global[ins.i_asi.i_rs1];
        !           504:        if (ins.i_loadstore.i_i)
        !           505:                addr += SIGN_EXT13(ins.i_simm13.i_simm13);
        !           506:        else
        !           507:                addr += tf->tf_global[ins.i_asi.i_rs2];
        !           508:
        !           509:        if (asi < ASI_PRIMARY) {
        !           510:                /* privileged asi */
        !           511:                trapsignal(p, SIGILL, 0, ILL_PRVOPC, sv);
        !           512:                return (0);
        !           513:        }
        !           514:        if (asi > ASI_SECONDARY_NOFAULT_LITTLE ||
        !           515:            (asi > ASI_SECONDARY_NOFAULT && asi < ASI_PRIMARY_LITTLE)) {
        !           516:                /* architecturally undefined user ASI's */
        !           517:                goto segv;
        !           518:        }
        !           519:
        !           520:        if ((freg & 3) != 0) {
        !           521:                /* only valid for %fN where N % 4 = 0 */
        !           522:                trapsignal(p, SIGILL, 0, ILL_ILLOPN, sv);
        !           523:                return (0);
        !           524:        }
        !           525:
        !           526:        if ((p->p_md.md_flags & MDP_FIXALIGN) == 0 && (addr & 3) != 0) {
        !           527:                /*
        !           528:                 * If process doesn't want us to fix alignment and the
        !           529:                 * request isn't aligned, kill it.
        !           530:                 */
        !           531:                trapsignal(p, SIGBUS, 0, BUS_ADRALN, sv);
        !           532:                return (0);
        !           533:        }
        !           534:
        !           535:        fs = p->p_md.md_fpstate;
        !           536:        if (fs == NULL) {
        !           537:                /* don't currently have an fpu context, get one */
        !           538:                fs = malloc(sizeof(*fs), M_SUBPROC, M_WAITOK);
        !           539:                *fs = initfpstate;
        !           540:                fs->fs_qsize = 0;
        !           541:                p->p_md.md_fpstate = fs;
        !           542:        }
        !           543:        if (fpproc != p) {
        !           544:                /* make this process the current holder of the fpu */
        !           545:                if (fpproc != NULL)
        !           546:                        savefpstate(fpproc->p_md.md_fpstate);
        !           547:                fpproc = p;
        !           548:        }
        !           549:        tf->tf_tstate |= TSTATE_PEF;
        !           550:
        !           551:        /* Ok, try to do the actual operation (finally) */
        !           552:        if (isload) {
        !           553:                err = copyin((caddr_t)addr, buf, sizeof(buf));
        !           554:                if (err != 0 && (asi & 2) == 0)
        !           555:                        goto segv;
        !           556:                if (err == 0) {
        !           557:                        savefpstate(fs);
        !           558:                        if (asi & 8)
        !           559:                                swap_quad(buf);
        !           560:                        bcopy(buf, &fs->fs_regs[freg], sizeof(buf));
        !           561:                        loadfpstate(fs);
        !           562:                }
        !           563:        } else {
        !           564:                bcopy(&fs->fs_regs[freg], buf, sizeof(buf));
        !           565:                if (asi & 8)
        !           566:                        swap_quad(buf);
        !           567:                if (copyout(buf, (caddr_t)addr, sizeof(buf)) && (asi & 2) == 0)
        !           568:                        goto segv;
        !           569:        }
        !           570:
        !           571:        return (1);
        !           572:
        !           573: segv:
        !           574:        trapsignal(p, SIGSEGV, isload ? VM_PROT_READ : VM_PROT_WRITE,
        !           575:            SEGV_MAPERR, sv);
        !           576:        return (0);
        !           577: }
        !           578:
        !           579: int
        !           580: emul_popc(int32_t insv, struct proc *p, union sigval sv, struct trapframe *tf)
        !           581: {
        !           582:        u_int64_t val, ret = 0;
        !           583:        union instr ins;
        !           584:
        !           585:        ins.i_int = insv;
        !           586:        if (ins.i_simm13.i_i == 0)
        !           587:                val = tf->tf_global[ins.i_asi.i_rs2];
        !           588:        else
        !           589:                val = SIGN_EXT13(ins.i_simm13.i_simm13);
        !           590:
        !           591:        for (; val != 0; val >>= 1)
        !           592:                ret += val & 1;
        !           593:
        !           594:        tf->tf_global[ins.i_asi.i_rd] = ret;
        !           595:        return (1);
        !           596: }

CVSweb