2 * Copyright (c) 2012 Rob Clark <robdclark@gmail.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 #include "freedreno_util.h"
34 #define DEBUG_MSG(f, ...) do { if (0) DBG(f, ##__VA_ARGS__); } while (0)
35 #define WARN_MSG(f, ...) DBG("WARN: "f, ##__VA_ARGS__)
36 #define ERROR_MSG(f, ...) DBG("ERROR: "f, ##__VA_ARGS__)
40 static int cf_emit(struct ir_cf
*cf
, instr_cf_t
*instr
);
42 static int instr_emit(struct ir_instruction
*instr
, uint32_t *dwords
,
43 uint32_t idx
, struct ir_shader_info
*info
);
45 static void reg_update_stats(struct ir_register
*reg
,
46 struct ir_shader_info
*info
, bool dest
);
47 static uint32_t reg_fetch_src_swiz(struct ir_register
*reg
, uint32_t n
);
48 static uint32_t reg_fetch_dst_swiz(struct ir_register
*reg
);
49 static uint32_t reg_alu_dst_swiz(struct ir_register
*reg
);
50 static uint32_t reg_alu_src_swiz(struct ir_register
*reg
);
52 /* simple allocator to carve allocations out of an up-front allocated heap,
53 * so that we can free everything easily in one shot.
55 static void * ir_alloc(struct ir_shader
*shader
, int sz
)
57 void *ptr
= &shader
->heap
[shader
->heap_idx
];
58 shader
->heap_idx
+= ALIGN(sz
, 4);
62 static char * ir_strdup(struct ir_shader
*shader
, const char *str
)
66 int len
= strlen(str
);
67 ptr
= ir_alloc(shader
, len
+1);
68 memcpy(ptr
, str
, len
);
74 struct ir_shader
* ir_shader_create(void)
77 return calloc(1, sizeof(struct ir_shader
));
80 void ir_shader_destroy(struct ir_shader
*shader
)
86 /* resolve addr/cnt/sequence fields in the individual CF's */
87 static int shader_resolve(struct ir_shader
*shader
, struct ir_shader_info
*info
)
93 addr
= shader
->cfs_count
/ 2;
94 for (i
= 0; i
< shader
->cfs_count
; i
++) {
95 struct ir_cf
*cf
= shader
->cfs
[i
];
96 if ((cf
->cf_type
== EXEC
) || (cf
->cf_type
== EXEC_END
)) {
97 uint32_t sequence
= 0;
99 if (cf
->exec
.addr
&& (cf
->exec
.addr
!= addr
))
100 WARN_MSG("invalid addr '%d' at CF %d", cf
->exec
.addr
, i
);
101 if (cf
->exec
.cnt
&& (cf
->exec
.cnt
!= cf
->exec
.instrs_count
))
102 WARN_MSG("invalid cnt '%d' at CF %d", cf
->exec
.cnt
, i
);
104 for (j
= cf
->exec
.instrs_count
- 1; j
>= 0; j
--) {
105 struct ir_instruction
*instr
= cf
->exec
.instrs
[j
];
107 if (instr
->instr_type
== IR_FETCH
)
113 cf
->exec
.addr
= addr
;
114 cf
->exec
.cnt
= cf
->exec
.instrs_count
;
115 cf
->exec
.sequence
= sequence
;
117 addr
+= cf
->exec
.instrs_count
;
121 info
->sizedwords
= 3 * addr
;
126 void * ir_shader_assemble(struct ir_shader
*shader
, struct ir_shader_info
*info
)
129 uint32_t *ptr
, *dwords
= NULL
;
133 info
->sizedwords
= 0;
135 info
->max_input_reg
= 0;
136 info
->regs_written
= 0;
138 /* we need an even # of CF's.. insert a NOP if needed */
139 if (shader
->cfs_count
!= ALIGN(shader
->cfs_count
, 2))
140 ir_cf_create(shader
, NOP
);
142 /* first pass, resolve sizes and addresses: */
143 ret
= shader_resolve(shader
, info
);
145 ERROR_MSG("resolve failed: %d", ret
);
149 ptr
= dwords
= calloc(1, 4 * info
->sizedwords
);
151 /* second pass, emit CF program in pairs: */
152 for (i
= 0; i
< shader
->cfs_count
; i
+= 2) {
153 instr_cf_t
*cfs
= (instr_cf_t
*)ptr
;
154 ret
= cf_emit(shader
->cfs
[i
], &cfs
[0]);
156 ERROR_MSG("CF emit failed: %d\n", ret
);
159 ret
= cf_emit(shader
->cfs
[i
+1], &cfs
[1]);
161 ERROR_MSG("CF emit failed: %d\n", ret
);
165 assert((ptr
- dwords
) <= info
->sizedwords
);
168 /* third pass, emit ALU/FETCH: */
169 for (i
= 0; i
< shader
->cfs_count
; i
++) {
170 struct ir_cf
*cf
= shader
->cfs
[i
];
171 if ((cf
->cf_type
== EXEC
) || (cf
->cf_type
== EXEC_END
)) {
172 for (j
= 0; j
< cf
->exec
.instrs_count
; j
++) {
173 ret
= instr_emit(cf
->exec
.instrs
[j
], ptr
, idx
++, info
);
175 ERROR_MSG("instruction emit failed: %d", ret
);
179 assert((ptr
- dwords
) <= info
->sizedwords
);
192 struct ir_attribute
* ir_attribute_create(struct ir_shader
*shader
,
193 int rstart
, int num
, const char *name
)
195 struct ir_attribute
*a
= ir_alloc(shader
, sizeof(struct ir_attribute
));
196 DEBUG_MSG("R%d-R%d: %s", rstart
, rstart
+ num
- 1, name
);
197 a
->name
= ir_strdup(shader
, name
);
200 assert(shader
->attributes_count
< ARRAY_SIZE(shader
->attributes
));
201 shader
->attributes
[shader
->attributes_count
++] = a
;
205 struct ir_const
* ir_const_create(struct ir_shader
*shader
,
206 int cstart
, float v0
, float v1
, float v2
, float v3
)
208 struct ir_const
*c
= ir_alloc(shader
, sizeof(struct ir_const
));
209 DEBUG_MSG("C%d: %f, %f, %f, %f", cstart
, v0
, v1
, v2
, v3
);
215 assert(shader
->consts_count
< ARRAY_SIZE(shader
->consts
));
216 shader
->consts
[shader
->consts_count
++] = c
;
220 struct ir_sampler
* ir_sampler_create(struct ir_shader
*shader
,
221 int idx
, const char *name
)
223 struct ir_sampler
*s
= ir_alloc(shader
, sizeof(struct ir_sampler
));
224 DEBUG_MSG("CONST(%d): %s", idx
, name
);
225 s
->name
= ir_strdup(shader
, name
);
227 assert(shader
->samplers_count
< ARRAY_SIZE(shader
->samplers
));
228 shader
->samplers
[shader
->samplers_count
++] = s
;
232 struct ir_uniform
* ir_uniform_create(struct ir_shader
*shader
,
233 int cstart
, int num
, const char *name
)
235 struct ir_uniform
*u
= ir_alloc(shader
, sizeof(struct ir_uniform
));
236 DEBUG_MSG("C%d-C%d: %s", cstart
, cstart
+ num
- 1, name
);
237 u
->name
= ir_strdup(shader
, name
);
240 assert(shader
->uniforms_count
< ARRAY_SIZE(shader
->uniforms
));
241 shader
->uniforms
[shader
->uniforms_count
++] = u
;
245 struct ir_varying
* ir_varying_create(struct ir_shader
*shader
,
246 int rstart
, int num
, const char *name
)
248 struct ir_varying
*v
= ir_alloc(shader
, sizeof(struct ir_varying
));
249 DEBUG_MSG("R%d-R%d: %s", rstart
, rstart
+ num
- 1, name
);
250 v
->name
= ir_strdup(shader
, name
);
253 assert(shader
->varyings_count
< ARRAY_SIZE(shader
->varyings
));
254 shader
->varyings
[shader
->varyings_count
++] = v
;
259 struct ir_cf
* ir_cf_create(struct ir_shader
*shader
, instr_cf_opc_t cf_type
)
261 struct ir_cf
*cf
= ir_alloc(shader
, sizeof(struct ir_cf
));
262 DEBUG_MSG("%d", cf_type
);
264 cf
->cf_type
= cf_type
;
265 assert(shader
->cfs_count
< ARRAY_SIZE(shader
->cfs
));
266 shader
->cfs
[shader
->cfs_count
++] = cf
;
275 static int cf_emit(struct ir_cf
*cf
, instr_cf_t
*instr
)
277 memset(instr
, 0, sizeof(*instr
));
279 instr
->opc
= cf
->cf_type
;
281 switch (cf
->cf_type
) {
286 assert(cf
->exec
.addr
<= 0x1ff);
287 assert(cf
->exec
.cnt
<= 0x6);
288 assert(cf
->exec
.sequence
<= 0xfff);
289 instr
->exec
.address
= cf
->exec
.addr
;
290 instr
->exec
.count
= cf
->exec
.cnt
;
291 instr
->exec
.serialize
= cf
->exec
.sequence
;
294 assert(cf
->alloc
.size
<= 0xf);
295 instr
->alloc
.size
= cf
->alloc
.size
;
296 switch (cf
->alloc
.type
) {
298 case SQ_PARAMETER_PIXEL
:
299 instr
->alloc
.buffer_select
= cf
->alloc
.type
;
302 ERROR_MSG("invalid alloc type: %d", cf
->alloc
.type
);
309 case COND_PRED_EXEC_END
:
315 case COND_EXEC_PRED_CLEAN
:
316 case COND_EXEC_PRED_CLEAN_END
:
317 case MARK_VS_FETCH_DONE
:
326 struct ir_instruction
* ir_instr_create(struct ir_cf
*cf
, int instr_type
)
328 struct ir_instruction
*instr
=
329 ir_alloc(cf
->shader
, sizeof(struct ir_instruction
));
330 DEBUG_MSG("%d", instr_type
);
331 instr
->shader
= cf
->shader
;
332 instr
->pred
= cf
->shader
->pred
;
333 instr
->instr_type
= instr_type
;
334 assert(cf
->exec
.instrs_count
< ARRAY_SIZE(cf
->exec
.instrs
));
335 cf
->exec
.instrs
[cf
->exec
.instrs_count
++] = instr
;
341 * FETCH instructions:
344 static int instr_emit_fetch(struct ir_instruction
*instr
,
345 uint32_t *dwords
, uint32_t idx
,
346 struct ir_shader_info
*info
)
348 instr_fetch_t
*fetch
= (instr_fetch_t
*)dwords
;
350 struct ir_register
*dst_reg
= instr
->regs
[reg
++];
351 struct ir_register
*src_reg
= instr
->regs
[reg
++];
353 memset(fetch
, 0, sizeof(*fetch
));
355 reg_update_stats(dst_reg
, info
, true);
356 reg_update_stats(src_reg
, info
, false);
358 fetch
->opc
= instr
->fetch
.opc
;
360 if (instr
->fetch
.opc
== VTX_FETCH
) {
361 instr_fetch_vtx_t
*vtx
= &fetch
->vtx
;
363 assert(instr
->fetch
.stride
<= 0xff);
364 assert(instr
->fetch
.fmt
<= 0x3f);
365 assert(instr
->fetch
.const_idx
<= 0x1f);
366 assert(instr
->fetch
.const_idx_sel
<= 0x3);
368 vtx
->src_reg
= src_reg
->num
;
369 vtx
->src_swiz
= reg_fetch_src_swiz(src_reg
, 1);
370 vtx
->dst_reg
= dst_reg
->num
;
371 vtx
->dst_swiz
= reg_fetch_dst_swiz(dst_reg
);
372 vtx
->must_be_one
= 1;
373 vtx
->const_index
= instr
->fetch
.const_idx
;
374 vtx
->const_index_sel
= instr
->fetch
.const_idx_sel
;
375 vtx
->format_comp_all
= !!instr
->fetch
.is_signed
;
376 vtx
->num_format_all
= !instr
->fetch
.is_normalized
;
377 vtx
->format
= instr
->fetch
.fmt
;
378 vtx
->stride
= instr
->fetch
.stride
;
379 vtx
->offset
= instr
->fetch
.offset
;
381 if (instr
->pred
!= IR_PRED_NONE
) {
382 vtx
->pred_select
= 1;
383 vtx
->pred_condition
= (instr
->pred
== IR_PRED_EQ
) ? 1 : 0;
386 /* XXX seems like every FETCH but the first has
389 vtx
->reserved3
= (idx
> 0) ? 0x1 : 0x0;
390 vtx
->reserved0
= (idx
> 0) ? 0x2 : 0x3;
391 } else if (instr
->fetch
.opc
== TEX_FETCH
) {
392 instr_fetch_tex_t
*tex
= &fetch
->tex
;
394 assert(instr
->fetch
.const_idx
<= 0x1f);
396 tex
->src_reg
= src_reg
->num
;
397 tex
->src_swiz
= reg_fetch_src_swiz(src_reg
, 3);
398 tex
->dst_reg
= dst_reg
->num
;
399 tex
->dst_swiz
= reg_fetch_dst_swiz(dst_reg
);
400 tex
->const_idx
= instr
->fetch
.const_idx
;
401 tex
->mag_filter
= TEX_FILTER_USE_FETCH_CONST
;
402 tex
->min_filter
= TEX_FILTER_USE_FETCH_CONST
;
403 tex
->mip_filter
= TEX_FILTER_USE_FETCH_CONST
;
404 tex
->aniso_filter
= ANISO_FILTER_USE_FETCH_CONST
;
405 tex
->arbitrary_filter
= ARBITRARY_FILTER_USE_FETCH_CONST
;
406 tex
->vol_mag_filter
= TEX_FILTER_USE_FETCH_CONST
;
407 tex
->vol_min_filter
= TEX_FILTER_USE_FETCH_CONST
;
408 tex
->use_comp_lod
= 1;
409 tex
->sample_location
= SAMPLE_CENTER
;
411 if (instr
->pred
!= IR_PRED_NONE
) {
412 tex
->pred_select
= 1;
413 tex
->pred_condition
= (instr
->pred
== IR_PRED_EQ
) ? 1 : 0;
417 ERROR_MSG("invalid fetch opc: %d\n", instr
->fetch
.opc
);
428 static int instr_emit_alu(struct ir_instruction
*instr
, uint32_t *dwords
,
429 struct ir_shader_info
*info
)
432 instr_alu_t
*alu
= (instr_alu_t
*)dwords
;
433 struct ir_register
*dst_reg
= instr
->regs
[reg
++];
434 struct ir_register
*src1_reg
;
435 struct ir_register
*src2_reg
;
436 struct ir_register
*src3_reg
;
438 memset(alu
, 0, sizeof(*alu
));
440 /* handle instructions w/ 3 src operands: */
441 switch (instr
->alu
.vector_opc
) {
447 /* note: disassembler lists 3rd src first, ie:
448 * MULADDv Rdst = Rsrc3 + (Rsrc1 * Rsrc2)
449 * which is the reason for this strange ordering.
451 src3_reg
= instr
->regs
[reg
++];
458 src1_reg
= instr
->regs
[reg
++];
459 src2_reg
= instr
->regs
[reg
++];
461 reg_update_stats(dst_reg
, info
, true);
462 reg_update_stats(src1_reg
, info
, false);
463 reg_update_stats(src2_reg
, info
, false);
465 assert((dst_reg
->flags
& ~IR_REG_EXPORT
) == 0);
466 assert(!dst_reg
->swizzle
|| (strlen(dst_reg
->swizzle
) == 4));
467 assert((src1_reg
->flags
& IR_REG_EXPORT
) == 0);
468 assert(!src1_reg
->swizzle
|| (strlen(src1_reg
->swizzle
) == 4));
469 assert((src2_reg
->flags
& IR_REG_EXPORT
) == 0);
470 assert(!src2_reg
->swizzle
|| (strlen(src2_reg
->swizzle
) == 4));
472 if (instr
->alu
.vector_opc
== ~0) {
473 alu
->vector_opc
= MAXv
;
474 alu
->vector_write_mask
= 0;
476 alu
->vector_opc
= instr
->alu
.vector_opc
;
477 alu
->vector_write_mask
= reg_alu_dst_swiz(dst_reg
);
480 alu
->vector_dest
= dst_reg
->num
;
481 alu
->export_data
= !!(dst_reg
->flags
& IR_REG_EXPORT
);
483 // TODO predicate case/condition.. need to add to parser
485 alu
->src2_reg
= src2_reg
->num
;
486 alu
->src2_swiz
= reg_alu_src_swiz(src2_reg
);
487 alu
->src2_reg_negate
= !!(src2_reg
->flags
& IR_REG_NEGATE
);
488 alu
->src2_reg_abs
= !!(src2_reg
->flags
& IR_REG_ABS
);
489 alu
->src2_sel
= !(src2_reg
->flags
& IR_REG_CONST
);
491 alu
->src1_reg
= src1_reg
->num
;
492 alu
->src1_swiz
= reg_alu_src_swiz(src1_reg
);
493 alu
->src1_reg_negate
= !!(src1_reg
->flags
& IR_REG_NEGATE
);
494 alu
->src1_reg_abs
= !!(src1_reg
->flags
& IR_REG_ABS
);
495 alu
->src1_sel
= !(src1_reg
->flags
& IR_REG_CONST
);
497 alu
->vector_clamp
= instr
->alu
.vector_clamp
;
498 alu
->scalar_clamp
= instr
->alu
.scalar_clamp
;
500 if (instr
->alu
.scalar_opc
!= ~0) {
501 struct ir_register
*sdst_reg
= instr
->regs
[reg
++];
503 reg_update_stats(sdst_reg
, info
, true);
505 assert(sdst_reg
->flags
== dst_reg
->flags
);
508 assert(src3_reg
== instr
->regs
[reg
++]);
510 src3_reg
= instr
->regs
[reg
++];
513 alu
->scalar_dest
= sdst_reg
->num
;
514 alu
->scalar_write_mask
= reg_alu_dst_swiz(sdst_reg
);
515 alu
->scalar_opc
= instr
->alu
.scalar_opc
;
517 /* not sure if this is required, but adreno compiler seems
518 * to always set scalar opc to MAXs if it is not used:
520 alu
->scalar_opc
= MAXs
;
524 reg_update_stats(src3_reg
, info
, false);
526 alu
->src3_reg
= src3_reg
->num
;
527 alu
->src3_swiz
= reg_alu_src_swiz(src3_reg
);
528 alu
->src3_reg_negate
= !!(src3_reg
->flags
& IR_REG_NEGATE
);
529 alu
->src3_reg_abs
= !!(src3_reg
->flags
& IR_REG_ABS
);
530 alu
->src3_sel
= !(src3_reg
->flags
& IR_REG_CONST
);
532 /* not sure if this is required, but adreno compiler seems
533 * to always set register bank for 3rd src if unused:
538 if (instr
->pred
!= IR_PRED_NONE
) {
539 alu
->pred_select
= (instr
->pred
== IR_PRED_EQ
) ? 3 : 2;
545 static int instr_emit(struct ir_instruction
*instr
, uint32_t *dwords
,
546 uint32_t idx
, struct ir_shader_info
*info
)
548 switch (instr
->instr_type
) {
549 case IR_FETCH
: return instr_emit_fetch(instr
, dwords
, idx
, info
);
550 case IR_ALU
: return instr_emit_alu(instr
, dwords
, info
);
556 struct ir_register
* ir_reg_create(struct ir_instruction
*instr
,
557 int num
, const char *swizzle
, int flags
)
559 struct ir_register
*reg
=
560 ir_alloc(instr
->shader
, sizeof(struct ir_register
));
561 DEBUG_MSG("%x, %d, %s", flags
, num
, swizzle
);
562 assert(num
<= REG_MASK
);
565 reg
->swizzle
= ir_strdup(instr
->shader
, swizzle
);
566 assert(instr
->regs_count
< ARRAY_SIZE(instr
->regs
));
567 instr
->regs
[instr
->regs_count
++] = reg
;
571 static void reg_update_stats(struct ir_register
*reg
,
572 struct ir_shader_info
*info
, bool dest
)
574 if (!(reg
->flags
& (IR_REG_CONST
|IR_REG_EXPORT
))) {
575 info
->max_reg
= max(info
->max_reg
, reg
->num
);
578 info
->regs_written
|= (1 << reg
->num
);
579 } else if (!(info
->regs_written
& (1 << reg
->num
))) {
580 /* for registers that haven't been written, they must be an
581 * input register that the thread scheduler (presumably?)
582 * needs to know about:
584 info
->max_input_reg
= max(info
->max_input_reg
, reg
->num
);
589 static uint32_t reg_fetch_src_swiz(struct ir_register
*reg
, uint32_t n
)
594 assert(reg
->flags
== 0);
595 assert(reg
->swizzle
);
597 DEBUG_MSG("fetch src R%d.%s", reg
->num
, reg
->swizzle
);
599 for (i
= n
-1; i
>= 0; i
--) {
601 switch (reg
->swizzle
[i
]) {
603 ERROR_MSG("invalid fetch src swizzle: %s", reg
->swizzle
);
604 case 'x': swiz
|= 0x0; break;
605 case 'y': swiz
|= 0x1; break;
606 case 'z': swiz
|= 0x2; break;
607 case 'w': swiz
|= 0x3; break;
614 static uint32_t reg_fetch_dst_swiz(struct ir_register
*reg
)
619 assert(reg
->flags
== 0);
620 assert(!reg
->swizzle
|| (strlen(reg
->swizzle
) == 4));
622 DEBUG_MSG("fetch dst R%d.%s", reg
->num
, reg
->swizzle
);
625 for (i
= 3; i
>= 0; i
--) {
627 switch (reg
->swizzle
[i
]) {
629 ERROR_MSG("invalid dst swizzle: %s", reg
->swizzle
);
630 case 'x': swiz
|= 0x0; break;
631 case 'y': swiz
|= 0x1; break;
632 case 'z': swiz
|= 0x2; break;
633 case 'w': swiz
|= 0x3; break;
634 case '0': swiz
|= 0x4; break;
635 case '1': swiz
|= 0x5; break;
636 case '_': swiz
|= 0x7; break;
646 /* actually, a write-mask */
647 static uint32_t reg_alu_dst_swiz(struct ir_register
*reg
)
652 assert((reg
->flags
& ~IR_REG_EXPORT
) == 0);
653 assert(!reg
->swizzle
|| (strlen(reg
->swizzle
) == 4));
655 DEBUG_MSG("alu dst R%d.%s", reg
->num
, reg
->swizzle
);
658 for (i
= 3; i
>= 0; i
--) {
660 if (reg
->swizzle
[i
] == "xyzw"[i
]) {
662 } else if (reg
->swizzle
[i
] != '_') {
663 ERROR_MSG("invalid dst swizzle: %s", reg
->swizzle
);
674 static uint32_t reg_alu_src_swiz(struct ir_register
*reg
)
679 assert((reg
->flags
& IR_REG_EXPORT
) == 0);
680 assert(!reg
->swizzle
|| (strlen(reg
->swizzle
) == 4));
682 DEBUG_MSG("vector src R%d.%s", reg
->num
, reg
->swizzle
);
685 for (i
= 3; i
>= 0; i
--) {
687 switch (reg
->swizzle
[i
]) {
689 ERROR_MSG("invalid vector src swizzle: %s", reg
->swizzle
);
690 case 'x': swiz
|= (0x0 - i
) & 0x3; break;
691 case 'y': swiz
|= (0x1 - i
) & 0x3; break;
692 case 'z': swiz
|= (0x2 - i
) & 0x3; break;
693 case 'w': swiz
|= (0x3 - i
) & 0x3; break;