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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 #pragma ident "@(#)asm.c 1.12 09/05/26 SMI" 23 24 /* 25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 /* 30 * 31 * routines for writing SPARC V9/Intel machine code. All could be macros 32 * but speed is not that important to me when this code is run 33 * 34 * See "The SPARC Architecture Manual" and 35 * "Intel Architecture Software Developer's Manual" for more info. 36 */ 37 38 #include <sys/types.h> 39 /*LINTED*/ 40 #include "asm.h" 41 42 #if __sparc 43 #define N5BITS 0x1f 44 #define N13BITS 0x1fff 45 #define N22BITS 0x3fffff 46 47 uint_t 48 add_asm(ushort_t rd, ushort_t rs1, char i, ushort_t x) 49 { 50 uint_t ret; 51 ret = ((uint_t)0x2 << 30) | ((rd & N5BITS) << 25) | 52 ((rs1 & N5BITS) << 14) | ((0x1 & i) << 13) | (N13BITS & x); 53 return (ret); 54 } 55 uint_t 56 sllx_asm(ushort_t rd, ushort_t rs1, ushort_t cnt) 57 { 58 uint_t ret; 59 ret = ((uint_t)1 << 31) | (rd << 25) | (0x25 << 19) | 60 (rs1 << 14) | (0x3 << 12) | (1 << 13) | (N13BITS & cnt); 61 return (ret); 62 } 63 uint_t 64 sethi_asm(ushort_t const22, ushort_t rd) 65 { 66 uint_t ret; 67 68 ret = ((N5BITS & rd) << 25) | (0x4 << 22) | (N22BITS & const22); 69 return (ret); 70 } 71 uint_t 72 jmpl_asm(ushort_t rd, ushort_t rs1, char i, ushort_t x) 73 { 74 uint_t ret; 75 76 ret = ((uint_t)1 << 31) | (rd << 25) | (0x38 << 19) | (rs1 << 14) | 77 (i << 13) | (N13BITS & x); 78 return (ret); 79 } 80 uint_t 81 bn_asm(char a, uint_t x) 82 { 83 uint_t ret; 84 85 ret = (a << 29) | (0x2 << 22) | (N22BITS & x); 86 return (ret); 87 } 88 uint_t 89 ba_asm(char a, uint_t x) 90 { 91 uint_t ret; 92 93 ret = (a << 29) | (0x8 << 25) | (0x2 << 22) | (N22BITS & x); 94 return (ret); 95 } 96 uint_t 97 save_asm(ushort_t rd, ushort_t rs1, char i, ushort_t x) 98 { 99 uint_t ret; 100 101 ret = ((uint_t)1 << 31) | (rd << 25) | (0x3c << 19) | (rs1 << 14) | 102 (i << 13) | (N13BITS & x); 103 return (ret); 104 } 105 uint_t 106 restore_asm(ushort_t rd, ushort_t rs1, char i, ushort_t x) 107 { 108 uint_t ret; 109 110 ret = ((uint_t)1 << 31) | (rd << 25) | (0x3d << 19) | (rs1 << 14) | 111 (i << 13) | (N13BITS & x); 112 return (ret); 113 } 114 #elif __i386 /* Intel */ || __amd64 115 116 /* 117 * Sadly, due to the varying instruction size inherent with CISC 118 * the assembler generated will be interspersed with NOPs. Padding 119 * things out like this seems like the simplest way to fit in with 120 * the current code which assumes easy multiples of 32 bits. 121 */ 122 123 124 #ifdef __amd64 125 126 varlen 127 mov32_asm(uint32_t imm32, ushort_t reg) 128 { 129 varlen ret; 130 131 ret.thirtytwo[0] = ((uint32_t)(0xb8+reg) << 24) | 0x909090; 132 ret.thirtytwo[1] = imm32; 133 134 return (ret); 135 } 136 varlen 137 movl_asm(uint64_t imm64, ushort_t reg) 138 { 139 varlen ret; 140 141 ret.thirtytwo[0] = ((uint32_t)(0xb8+reg) << 24) | 0x489090; 142 ret.thirtytwo[1] = (uint32_t)LOWER32(imm64); 143 ret.thirtytwo[2] = (uint32_t)UPPER32(imm64); 144 145 return (ret); 146 } 147 148 varlen 149 pushl_asm(uint32_t imm32) /* pushl <imm64> */ 150 { 151 varlen ret; 152 153 ret.thirtytwo[0] = (uint32_t)0x68909090; 154 ret.thirtytwo[1] = imm32; 155 156 return (ret); 157 } 158 159 varlen 160 jmp_asm(uint32_t offset) 161 { 162 varlen ret; 163 164 ret.thirtytwo[0] = (uint32_t)0xe9909090; 165 ret.thirtytwo[1] = offset; 166 ret.thirtytwo[2] = 0; 167 168 return (ret); 169 } 170 #else 171 172 varlen 173 movl_asm(uint32_t imm32, ushort_t reg) 174 { 175 varlen ret; 176 177 ret.thirtytwo[0] = ((uint32_t)(0xb8+reg) << 24) | 0x909090; 178 ret.thirtytwo[1] = imm32; 179 180 return (ret); 181 } 182 183 varlen 184 pushl_asm(uint32_t imm32) /* pushl <imm32> */ 185 { 186 varlen ret; 187 188 ret.thirtytwo[0] = (uint32_t)0x68909090; 189 ret.thirtytwo[1] = imm32; 190 191 return (ret); 192 } 193 194 varlen 195 jmp_asm(uint32_t offset) 196 { 197 varlen ret; 198 199 ret.thirtytwo[0] = (uint32_t)0xe9909090; 200 ret.thirtytwo[1] = offset; 201 202 return (ret); 203 } 204 #endif 205 206 #else 207 #error "Unkown processor" 208 #endif 209