1 /**************************************************************************
2  *
3  * Copyright 2010 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20  * USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * The above copyright notice and this permission notice (including the
23  * next paragraph) shall be included in all copies or substantial portions
24  * of the Software.
25  *
26  **************************************************************************/
27 
28 
29 #include "util/u_debug.h"
30 
31 #include "lp_bld_type.h"
32 #include "lp_bld_debug.h"
33 #include "lp_bld_const.h"
34 #include "lp_bld_bitarit.h"
35 
36 
37 /**
38  * Return (a | b)
39  */
40 LLVMValueRef
lp_build_or(struct lp_build_context * bld,LLVMValueRef a,LLVMValueRef b)41 lp_build_or(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
42 {
43    LLVMBuilderRef builder = bld->gallivm->builder;
44    const struct lp_type type = bld->type;
45    LLVMValueRef res;
46 
47    assert(lp_check_value(type, a));
48    assert(lp_check_value(type, b));
49 
50    /* can't do bitwise ops on floating-point values */
51    if (type.floating) {
52       a = LLVMBuildBitCast(builder, a, bld->int_vec_type, "");
53       b = LLVMBuildBitCast(builder, b, bld->int_vec_type, "");
54    }
55 
56    res = LLVMBuildOr(builder, a, b, "");
57 
58    if (type.floating) {
59       res = LLVMBuildBitCast(builder, res, bld->vec_type, "");
60    }
61 
62    return res;
63 }
64 
65 /* bitwise XOR (a ^ b) */
66 LLVMValueRef
lp_build_xor(struct lp_build_context * bld,LLVMValueRef a,LLVMValueRef b)67 lp_build_xor(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
68 {
69    LLVMBuilderRef builder = bld->gallivm->builder;
70    const struct lp_type type = bld->type;
71    LLVMValueRef res;
72 
73    assert(lp_check_value(type, a));
74    assert(lp_check_value(type, b));
75 
76    /* can't do bitwise ops on floating-point values */
77    if (type.floating) {
78       a = LLVMBuildBitCast(builder, a, bld->int_vec_type, "");
79       b = LLVMBuildBitCast(builder, b, bld->int_vec_type, "");
80    }
81 
82    res = LLVMBuildXor(builder, a, b, "");
83 
84    if (type.floating) {
85       res = LLVMBuildBitCast(builder, res, bld->vec_type, "");
86    }
87 
88    return res;
89 }
90 
91 /**
92  * Return (a & b)
93  */
94 LLVMValueRef
lp_build_and(struct lp_build_context * bld,LLVMValueRef a,LLVMValueRef b)95 lp_build_and(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
96 {
97    LLVMBuilderRef builder = bld->gallivm->builder;
98    const struct lp_type type = bld->type;
99    LLVMValueRef res;
100 
101    assert(lp_check_value(type, a));
102    assert(lp_check_value(type, b));
103 
104    /* can't do bitwise ops on floating-point values */
105    if (type.floating) {
106       a = LLVMBuildBitCast(builder, a, bld->int_vec_type, "");
107       b = LLVMBuildBitCast(builder, b, bld->int_vec_type, "");
108    }
109 
110    res = LLVMBuildAnd(builder, a, b, "");
111 
112    if (type.floating) {
113       res = LLVMBuildBitCast(builder, res, bld->vec_type, "");
114    }
115 
116    return res;
117 }
118 
119 
120 /**
121  * Return (a & ~b)
122  */
123 LLVMValueRef
lp_build_andnot(struct lp_build_context * bld,LLVMValueRef a,LLVMValueRef b)124 lp_build_andnot(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
125 {
126    LLVMBuilderRef builder = bld->gallivm->builder;
127    const struct lp_type type = bld->type;
128    LLVMValueRef res;
129 
130    assert(lp_check_value(type, a));
131    assert(lp_check_value(type, b));
132 
133    /* can't do bitwise ops on floating-point values */
134    if (type.floating) {
135       a = LLVMBuildBitCast(builder, a, bld->int_vec_type, "");
136       b = LLVMBuildBitCast(builder, b, bld->int_vec_type, "");
137    }
138 
139    res = LLVMBuildNot(builder, b, "");
140    res = LLVMBuildAnd(builder, a, res, "");
141 
142    if (type.floating) {
143       res = LLVMBuildBitCast(builder, res, bld->vec_type, "");
144    }
145 
146    return res;
147 }
148 
149 /* bitwise NOT */
150 LLVMValueRef
lp_build_not(struct lp_build_context * bld,LLVMValueRef a)151 lp_build_not(struct lp_build_context *bld, LLVMValueRef a)
152 {
153    LLVMBuilderRef builder = bld->gallivm->builder;
154    const struct lp_type type = bld->type;
155    LLVMValueRef res;
156 
157    assert(lp_check_value(type, a));
158 
159    if (type.floating) {
160       a = LLVMBuildBitCast(builder, a, bld->int_vec_type, "");
161    }
162    res = LLVMBuildNot(builder, a, "");
163    if (type.floating) {
164       res = LLVMBuildBitCast(builder, res, bld->vec_type, "");
165    }
166    return res;
167 }
168 
169 /**
170  * Shift left.
171  */
172 LLVMValueRef
lp_build_shl(struct lp_build_context * bld,LLVMValueRef a,LLVMValueRef b)173 lp_build_shl(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
174 {
175    LLVMBuilderRef builder = bld->gallivm->builder;
176    const struct lp_type type = bld->type;
177    LLVMValueRef res;
178 
179    assert(!type.floating);
180 
181    assert(lp_check_value(type, a));
182    assert(lp_check_value(type, b));
183 
184    res = LLVMBuildShl(builder, a, b, "");
185 
186    return res;
187 }
188 
189 
190 /**
191  * Shift right.
192  */
193 LLVMValueRef
lp_build_shr(struct lp_build_context * bld,LLVMValueRef a,LLVMValueRef b)194 lp_build_shr(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
195 {
196    LLVMBuilderRef builder = bld->gallivm->builder;
197    const struct lp_type type = bld->type;
198    LLVMValueRef res;
199 
200    assert(!type.floating);
201 
202    assert(lp_check_value(type, a));
203    assert(lp_check_value(type, b));
204 
205    if (type.sign) {
206       res = LLVMBuildAShr(builder, a, b, "");
207    } else {
208       res = LLVMBuildLShr(builder, a, b, "");
209    }
210 
211    return res;
212 }
213 
214 
215 /**
216  * Shift left with immediate.
217  */
218 LLVMValueRef
lp_build_shl_imm(struct lp_build_context * bld,LLVMValueRef a,unsigned imm)219 lp_build_shl_imm(struct lp_build_context *bld, LLVMValueRef a, unsigned imm)
220 {
221    LLVMValueRef b = lp_build_const_int_vec(bld->gallivm, bld->type, imm);
222    assert(imm <= bld->type.width);
223    return lp_build_shl(bld, a, b);
224 }
225 
226 
227 /**
228  * Shift right with immediate.
229  */
230 LLVMValueRef
lp_build_shr_imm(struct lp_build_context * bld,LLVMValueRef a,unsigned imm)231 lp_build_shr_imm(struct lp_build_context *bld, LLVMValueRef a, unsigned imm)
232 {
233    LLVMValueRef b = lp_build_const_int_vec(bld->gallivm, bld->type, imm);
234    assert(imm <= bld->type.width);
235    return lp_build_shr(bld, a, b);
236 }
237