1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 /* 29 * Copyright (c) 2012 by Delphix. All rights reserved. 30 * Copyright (c) 2016 Pedro Giffuni. All rights reserved. 31 */ 32 33 #include <sys/types.h> 34 #include <sys/bitmap.h> 35 #include <assert.h> 36 #include <strings.h> 37 #include <stdlib.h> 38 39 #include <dt_regset.h> 40 #include <dt_impl.h> 41 42 dt_regset_t * 43 dt_regset_create(ulong_t nregs) 44 { 45 ulong_t n = BT_BITOUL(nregs); 46 dt_regset_t *drp = malloc(sizeof (dt_regset_t)); 47 48 if (drp == NULL) 49 return (NULL); 50 51 drp->dr_bitmap = calloc(n, sizeof (ulong_t)); 52 53 if (drp->dr_bitmap == NULL) { 54 dt_regset_destroy(drp); 55 return (NULL); 56 } 57 58 drp->dr_size = nregs; 59 60 return (drp); 61 } 62 63 void 64 dt_regset_destroy(dt_regset_t *drp) 65 { 66 free(drp->dr_bitmap); 67 free(drp); 68 } 69 70 void 71 dt_regset_reset(dt_regset_t *drp) 72 { 73 bzero(drp->dr_bitmap, sizeof (ulong_t) * BT_BITOUL(drp->dr_size)); 74 } 75 76 void 77 dt_regset_assert_free(dt_regset_t *drp) 78 { 79 int reg; 80 boolean_t fail = B_FALSE; 81 for (reg = 0; reg < drp->dr_size; reg++) { 82 if (BT_TEST(drp->dr_bitmap, reg) != 0) { 83 dt_dprintf("%%r%d was left allocated\n", reg); 84 fail = B_TRUE; 85 } 86 } 87 88 /* 89 * We set this during dtest runs to check for register leaks. 90 */ 91 if (fail && getenv("DTRACE_DEBUG_REGSET") != NULL) 92 abort(); 93 } 94 95 int 96 dt_regset_alloc(dt_regset_t *drp) 97 { 98 ulong_t nbits = drp->dr_size - 1; 99 ulong_t maxw = nbits >> BT_ULSHIFT; 100 ulong_t wx; 101 102 for (wx = 0; wx <= maxw; wx++) { 103 if (drp->dr_bitmap[wx] != ~0UL) 104 break; 105 } 106 107 if (wx <= maxw) { 108 ulong_t maxb = (wx == maxw) ? nbits & BT_ULMASK : BT_NBIPUL - 1; 109 ulong_t word = drp->dr_bitmap[wx]; 110 ulong_t bit, bx; 111 int reg; 112 113 for (bit = 1, bx = 0; bx <= maxb; bx++, bit <<= 1) { 114 if ((word & bit) == 0) { 115 reg = (int)((wx << BT_ULSHIFT) | bx); 116 BT_SET(drp->dr_bitmap, reg); 117 return (reg); 118 } 119 } 120 } 121 122 xyerror(D_NOREG, "Insufficient registers to generate code"); 123 /*NOTREACHED*/ 124 return (-1); 125 } 126 127 void 128 dt_regset_free(dt_regset_t *drp, int reg) 129 { 130 assert(reg >= 0 && reg < drp->dr_size); 131 assert(BT_TEST(drp->dr_bitmap, reg) != 0); 132 BT_CLEAR(drp->dr_bitmap, reg); 133 } 134