Home | History | Annotate | Download | only in diskomizer
      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