1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2019 Connor Abbott <cwabbott0@gmail.com> 3bf215546Sopenharmony_ci * Copyright (C) 2019 Lyude Paul <thatslyude@gmail.com> 4bf215546Sopenharmony_ci * Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com> 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 9bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 11bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 12bf215546Sopenharmony_ci * 13bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 14bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 15bf215546Sopenharmony_ci * Software. 16bf215546Sopenharmony_ci * 17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23bf215546Sopenharmony_ci * SOFTWARE. 24bf215546Sopenharmony_ci */ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#ifndef __bifrost_h__ 27bf215546Sopenharmony_ci#define __bifrost_h__ 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include <stdint.h> 30bf215546Sopenharmony_ci#include <stdbool.h> 31bf215546Sopenharmony_ci#include <string.h> 32bf215546Sopenharmony_ci#include <assert.h> 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#ifdef __cplusplus 35bf215546Sopenharmony_ciextern "C" { 36bf215546Sopenharmony_ci#endif 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#define BIFROST_DBG_MSGS 0x0001 39bf215546Sopenharmony_ci#define BIFROST_DBG_SHADERS 0x0002 40bf215546Sopenharmony_ci#define BIFROST_DBG_SHADERDB 0x0004 41bf215546Sopenharmony_ci#define BIFROST_DBG_VERBOSE 0x0008 42bf215546Sopenharmony_ci#define BIFROST_DBG_INTERNAL 0x0010 43bf215546Sopenharmony_ci#define BIFROST_DBG_NOSCHED 0x0020 44bf215546Sopenharmony_ci#define BIFROST_DBG_INORDER 0x0040 45bf215546Sopenharmony_ci#define BIFROST_DBG_NOVALIDATE 0x0080 46bf215546Sopenharmony_ci#define BIFROST_DBG_NOOPT 0x0100 47bf215546Sopenharmony_ci#define BIFROST_DBG_NOIDVS 0x0200 48bf215546Sopenharmony_ci#define BIFROST_DBG_NOSB 0x0400 49bf215546Sopenharmony_ci#define BIFROST_DBG_NOPRELOAD 0x0800 50bf215546Sopenharmony_ci#define BIFROST_DBG_SPILL 0x1000 51bf215546Sopenharmony_ci#define BIFROST_DBG_NOPSCHED 0x2000 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ciextern int bifrost_debug; 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_cienum bifrost_message_type { 56bf215546Sopenharmony_ci BIFROST_MESSAGE_NONE = 0, 57bf215546Sopenharmony_ci BIFROST_MESSAGE_VARYING = 1, 58bf215546Sopenharmony_ci BIFROST_MESSAGE_ATTRIBUTE = 2, 59bf215546Sopenharmony_ci BIFROST_MESSAGE_TEX = 3, 60bf215546Sopenharmony_ci BIFROST_MESSAGE_VARTEX = 4, 61bf215546Sopenharmony_ci BIFROST_MESSAGE_LOAD = 5, 62bf215546Sopenharmony_ci BIFROST_MESSAGE_STORE = 6, 63bf215546Sopenharmony_ci BIFROST_MESSAGE_ATOMIC = 7, 64bf215546Sopenharmony_ci BIFROST_MESSAGE_BARRIER = 8, 65bf215546Sopenharmony_ci BIFROST_MESSAGE_BLEND = 9, 66bf215546Sopenharmony_ci BIFROST_MESSAGE_TILE = 10, 67bf215546Sopenharmony_ci /* type 11 reserved */ 68bf215546Sopenharmony_ci BIFROST_MESSAGE_Z_STENCIL = 12, 69bf215546Sopenharmony_ci BIFROST_MESSAGE_ATEST = 13, 70bf215546Sopenharmony_ci BIFROST_MESSAGE_JOB = 14, 71bf215546Sopenharmony_ci BIFROST_MESSAGE_64BIT = 15 72bf215546Sopenharmony_ci}; 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_cienum bifrost_ftz { 75bf215546Sopenharmony_ci BIFROST_FTZ_DISABLE = 0, 76bf215546Sopenharmony_ci BIFROST_FTZ_DX11 = 1, 77bf215546Sopenharmony_ci BIFROST_FTZ_ALWAYS = 2, 78bf215546Sopenharmony_ci BIFROST_FTZ_ABRUPT = 3 79bf215546Sopenharmony_ci}; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_cienum bifrost_exceptions { 82bf215546Sopenharmony_ci BIFROST_EXCEPTIONS_ENABLED = 0, 83bf215546Sopenharmony_ci BIFROST_EXCEPTIONS_DISABLED = 1, 84bf215546Sopenharmony_ci BIFROST_EXCEPTIONS_PRECISE_DIVISION = 2, 85bf215546Sopenharmony_ci BIFROST_EXCEPTIONS_PRECISE_SQRT = 3, 86bf215546Sopenharmony_ci}; 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci/* Describes clause flow control, with respect to control flow and branch 89bf215546Sopenharmony_ci * reconvergence. 90bf215546Sopenharmony_ci * 91bf215546Sopenharmony_ci * Control flow may be considered back-to-back (execute clauses back-to-back), 92bf215546Sopenharmony_ci * non-back-to-back (switch warps after clause before the next clause), write 93bf215546Sopenharmony_ci * elision (back-to-back and elide register slot #3 write from the clause), or 94bf215546Sopenharmony_ci * end of shader. 95bf215546Sopenharmony_ci * 96bf215546Sopenharmony_ci * Branch reconvergence may be disabled, enabled unconditionally, or enabled 97bf215546Sopenharmony_ci * based on the program counter. A clause requires reconvergence if it has a 98bf215546Sopenharmony_ci * successor that can be executed without first executing the clause itself. 99bf215546Sopenharmony_ci * Separate iterations of a loop are treated separately here, so it is also the 100bf215546Sopenharmony_ci * case for a loop exit where the iteration count is not warp-invariant. 101bf215546Sopenharmony_ci * 102bf215546Sopenharmony_ci */ 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_cienum bifrost_flow { 105bf215546Sopenharmony_ci /* End-of-shader */ 106bf215546Sopenharmony_ci BIFROST_FLOW_END = 0, 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci /* Non back-to-back, PC-encoded reconvergence */ 109bf215546Sopenharmony_ci BIFROST_FLOW_NBTB_PC = 1, 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci /* Non back-to-back, unconditional reconvergence */ 112bf215546Sopenharmony_ci BIFROST_FLOW_NBTB_UNCONDITIONAL = 2, 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci /* Non back-to-back, no reconvergence */ 115bf215546Sopenharmony_ci BIFROST_FLOW_NBTB = 3, 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci /* Back-to-back, unconditional reconvergence */ 118bf215546Sopenharmony_ci BIFROST_FLOW_BTB_UNCONDITIONAL = 4, 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci /* Back-to-back, no reconvergence */ 121bf215546Sopenharmony_ci BIFROST_FLOW_BTB_NONE = 5, 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci /* Write elision, unconditional reconvergence */ 124bf215546Sopenharmony_ci BIFROST_FLOW_WE_UNCONDITIONAL = 6, 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci /* Write elision, no reconvergence */ 127bf215546Sopenharmony_ci BIFROST_FLOW_WE = 7, 128bf215546Sopenharmony_ci}; 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_cienum bifrost_slot { 131bf215546Sopenharmony_ci /* 0-5 are general purpose */ 132bf215546Sopenharmony_ci BIFROST_SLOT_ELDEST_DEPTH = 6, 133bf215546Sopenharmony_ci BIFROST_SLOT_ELDEST_COLOUR = 7, 134bf215546Sopenharmony_ci}; 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_cistruct bifrost_header { 137bf215546Sopenharmony_ci /* Reserved */ 138bf215546Sopenharmony_ci unsigned zero1 : 5; 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci /* Flush-to-zero mode, leave zero for GL */ 141bf215546Sopenharmony_ci enum bifrost_ftz flush_to_zero : 2; 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci /* Convert any infinite result of any floating-point operation to the 144bf215546Sopenharmony_ci * biggest representable number */ 145bf215546Sopenharmony_ci unsigned suppress_inf: 1; 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci /* Convert NaN to +0.0 */ 148bf215546Sopenharmony_ci unsigned suppress_nan : 1; 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci /* Floating-point excception handling mode */ 151bf215546Sopenharmony_ci enum bifrost_exceptions float_exceptions : 2; 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci /* Enum describing the flow control, which matters for handling 154bf215546Sopenharmony_ci * divergence and reconvergence efficiently */ 155bf215546Sopenharmony_ci enum bifrost_flow flow_control : 3; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci /* Reserved */ 158bf215546Sopenharmony_ci unsigned zero2 : 1; 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci /* Terminate discarded threads, rather than continuing execution. Set 161bf215546Sopenharmony_ci * for fragment shaders for standard GL behaviour of DISCARD. Also in a 162bf215546Sopenharmony_ci * fragment shader, this disables helper invocations, so cannot be used 163bf215546Sopenharmony_ci * in a shader that requires derivatives or texture LOD computation */ 164bf215546Sopenharmony_ci unsigned terminate_discarded_threads : 1; 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci /* If set, the hardware may prefetch the next clause. If false, the 167bf215546Sopenharmony_ci * hardware may not. Clear for unconditional branches. */ 168bf215546Sopenharmony_ci unsigned next_clause_prefetch : 1; 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci /* If set, a barrier will be inserted after the clause waiting for all 171bf215546Sopenharmony_ci * message passing instructions to read their staging registers, such 172bf215546Sopenharmony_ci * that it is safe for the next clause to write them. */ 173bf215546Sopenharmony_ci unsigned staging_barrier: 1; 174bf215546Sopenharmony_ci unsigned staging_register : 6; 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci /* Slots to wait on and slot to be used for message passing 177bf215546Sopenharmony_ci * instructions respectively */ 178bf215546Sopenharmony_ci unsigned dependency_wait : 8; 179bf215546Sopenharmony_ci unsigned dependency_slot : 3; 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci enum bifrost_message_type message_type : 5; 182bf215546Sopenharmony_ci enum bifrost_message_type next_message_type : 5; 183bf215546Sopenharmony_ci} __attribute__((packed)); 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_cienum bifrost_packed_src { 186bf215546Sopenharmony_ci BIFROST_SRC_PORT0 = 0, 187bf215546Sopenharmony_ci BIFROST_SRC_PORT1 = 1, 188bf215546Sopenharmony_ci BIFROST_SRC_PORT2 = 2, 189bf215546Sopenharmony_ci BIFROST_SRC_STAGE = 3, 190bf215546Sopenharmony_ci BIFROST_SRC_FAU_LO = 4, 191bf215546Sopenharmony_ci BIFROST_SRC_FAU_HI = 5, 192bf215546Sopenharmony_ci BIFROST_SRC_PASS_FMA = 6, 193bf215546Sopenharmony_ci BIFROST_SRC_PASS_ADD = 7, 194bf215546Sopenharmony_ci}; 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_cistruct bifrost_fma_inst { 197bf215546Sopenharmony_ci unsigned src0 : 3; 198bf215546Sopenharmony_ci unsigned op : 20; 199bf215546Sopenharmony_ci} __attribute__((packed)); 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_cistruct bifrost_add_inst { 202bf215546Sopenharmony_ci unsigned src0 : 3; 203bf215546Sopenharmony_ci unsigned op : 17; 204bf215546Sopenharmony_ci} __attribute__((packed)); 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_cienum branch_bit_size { 207bf215546Sopenharmony_ci BR_SIZE_32 = 0, 208bf215546Sopenharmony_ci BR_SIZE_16XX = 1, 209bf215546Sopenharmony_ci BR_SIZE_16YY = 2, 210bf215546Sopenharmony_ci // For the above combinations of bitsize and location, an extra bit is 211bf215546Sopenharmony_ci // encoded via comparing the sources. The only possible source of ambiguity 212bf215546Sopenharmony_ci // would be if the sources were the same, but then the branch condition 213bf215546Sopenharmony_ci // would be always true or always false anyways, so we can ignore it. But 214bf215546Sopenharmony_ci // this no longer works when comparing the y component to the x component, 215bf215546Sopenharmony_ci // since it's valid to compare the y component of a source against its own 216bf215546Sopenharmony_ci // x component. Instead, the extra bit is encoded via an extra bitsize. 217bf215546Sopenharmony_ci BR_SIZE_16YX0 = 3, 218bf215546Sopenharmony_ci BR_SIZE_16YX1 = 4, 219bf215546Sopenharmony_ci BR_SIZE_32_AND_16X = 5, 220bf215546Sopenharmony_ci BR_SIZE_32_AND_16Y = 6, 221bf215546Sopenharmony_ci // Used for comparisons with zero and always-true, see below. I think this 222bf215546Sopenharmony_ci // only works for integer comparisons. 223bf215546Sopenharmony_ci BR_SIZE_ZERO = 7, 224bf215546Sopenharmony_ci}; 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_cistruct bifrost_regs { 227bf215546Sopenharmony_ci unsigned fau_idx : 8; 228bf215546Sopenharmony_ci unsigned reg3 : 6; 229bf215546Sopenharmony_ci unsigned reg2 : 6; 230bf215546Sopenharmony_ci unsigned reg0 : 5; 231bf215546Sopenharmony_ci unsigned reg1 : 6; 232bf215546Sopenharmony_ci unsigned ctrl : 4; 233bf215546Sopenharmony_ci} __attribute__((packed)); 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci#define BIFROST_FMTC_CONSTANTS 0b0011 236bf215546Sopenharmony_ci#define BIFROST_FMTC_FINAL 0b0111 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_cistruct bifrost_fmt_constant { 239bf215546Sopenharmony_ci unsigned pos : 4; 240bf215546Sopenharmony_ci unsigned tag : 4; 241bf215546Sopenharmony_ci uint64_t imm_1 : 60; 242bf215546Sopenharmony_ci uint64_t imm_2 : 60; 243bf215546Sopenharmony_ci} __attribute__((packed)); 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci/* Clause formats, encoded in a table */ 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_cienum bi_clause_subword { 248bf215546Sopenharmony_ci /* Literal 3-bit values */ 249bf215546Sopenharmony_ci BI_CLAUSE_SUBWORD_LITERAL_0 = 0, 250bf215546Sopenharmony_ci /* etc */ 251bf215546Sopenharmony_ci BI_CLAUSE_SUBWORD_LITERAL_7 = 7, 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci /* The value of the corresponding tuple in the corresponding bits */ 254bf215546Sopenharmony_ci BI_CLAUSE_SUBWORD_TUPLE_0 = 8, 255bf215546Sopenharmony_ci /* etc */ 256bf215546Sopenharmony_ci BI_CLAUSE_SUBWORD_TUPLE_7 = 15, 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci /* Clause header */ 259bf215546Sopenharmony_ci BI_CLAUSE_SUBWORD_HEADER = 16, 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci /* Leave zero, but semantically distinct from literal 0 */ 262bf215546Sopenharmony_ci BI_CLAUSE_SUBWORD_RESERVED = 17, 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci /* Embedded constant 0 */ 265bf215546Sopenharmony_ci BI_CLAUSE_SUBWORD_CONSTANT = 18, 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci /* M bits controlling modifier for the constant */ 268bf215546Sopenharmony_ci BI_CLAUSE_SUBWORD_M = 19, 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci /* Z bit: 1 to begin encoding constants, 0 to terminate the clause */ 271bf215546Sopenharmony_ci BI_CLAUSE_SUBWORD_Z = 20, 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci /* Upper 3-bits of a given tuple and zero extended */ 274bf215546Sopenharmony_ci BI_CLAUSE_SUBWORD_UPPER_0 = 32, 275bf215546Sopenharmony_ci /* etc */ 276bf215546Sopenharmony_ci BI_CLAUSE_SUBWORD_UPPER_7 = BI_CLAUSE_SUBWORD_UPPER_0 + 7, 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci /* Upper 3-bits of two tuples, concatenated and zero-extended */ 279bf215546Sopenharmony_ci BI_CLAUSE_SUBWORD_UPPER_23 = BI_CLAUSE_SUBWORD_UPPER_0 + 23, 280bf215546Sopenharmony_ci BI_CLAUSE_SUBWORD_UPPER_56 = BI_CLAUSE_SUBWORD_UPPER_0 + 56, 281bf215546Sopenharmony_ci}; 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci#define L(x) ((enum bi_clause_subword)(BI_CLAUSE_SUBWORD_LITERAL_0 + x)) 284bf215546Sopenharmony_ci#define U(x) ((enum bi_clause_subword)(BI_CLAUSE_SUBWORD_UPPER_0 + x)) 285bf215546Sopenharmony_ci#define T(x) ((enum bi_clause_subword)(BI_CLAUSE_SUBWORD_TUPLE_0 + x)) 286bf215546Sopenharmony_ci#define EC BI_CLAUSE_SUBWORD_CONSTANT 287bf215546Sopenharmony_ci#define M BI_CLAUSE_SUBWORD_M 288bf215546Sopenharmony_ci#define Z BI_CLAUSE_SUBWORD_Z 289bf215546Sopenharmony_ci#define H BI_CLAUSE_SUBWORD_HEADER 290bf215546Sopenharmony_ci#define R BI_CLAUSE_SUBWORD_RESERVED 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_cistruct bi_clause_format { 293bf215546Sopenharmony_ci unsigned format; /* format number */ 294bf215546Sopenharmony_ci unsigned pos; /* index in the clause */ 295bf215546Sopenharmony_ci enum bi_clause_subword tag_1; /* 2-bits */ 296bf215546Sopenharmony_ci enum bi_clause_subword tag_2; /* 3-bits */ 297bf215546Sopenharmony_ci enum bi_clause_subword tag_3; /* 3-bits */ 298bf215546Sopenharmony_ci enum bi_clause_subword s0_s3; /* 60 bits */ 299bf215546Sopenharmony_ci enum bi_clause_subword s4; /* 15 bits */ 300bf215546Sopenharmony_ci enum bi_clause_subword s5_s6; /* 30 bits */ 301bf215546Sopenharmony_ci enum bi_clause_subword s7; /* 15 bits */ 302bf215546Sopenharmony_ci}; 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_cistatic const struct bi_clause_format bi_clause_formats[] = { 305bf215546Sopenharmony_ci { 0, 0, L(0), L(5), U(0), T(0), T(0), H, H }, 306bf215546Sopenharmony_ci { 0, 0, Z, L(1), U(0), T(0), T(0), H, H }, 307bf215546Sopenharmony_ci { 1, 1, Z, L(0), L(3), T(1), T(1), R, U(1) }, 308bf215546Sopenharmony_ci { 2, 1, L(0), L(4), U(1), T(1), T(1), T(2), T(2) }, 309bf215546Sopenharmony_ci { 3, 2, Z, L(0), L(4), EC, M, T(2), U(2) }, 310bf215546Sopenharmony_ci { 4, 2, L(0), L(0), L(1), T(3), T(3), T(2), U(23) }, 311bf215546Sopenharmony_ci { 4, 2, Z, L(0), L(5), T(3), T(3), T(2), U(23) }, 312bf215546Sopenharmony_ci { 5, 2, L(2), U(3), U(2), T(3), T(3), T(2), EC }, 313bf215546Sopenharmony_ci { 6, 3, Z, L(2), U(4), T(4), T(4), EC, EC }, 314bf215546Sopenharmony_ci { 7, 3, L(1), L(4), U(4), T(4), T(4), T(5), T(5) }, 315bf215546Sopenharmony_ci { 8, 4, Z, L(0), L(6), EC, M, T(5), U(5) }, 316bf215546Sopenharmony_ci { 9, 4, Z, L(0), L(7), T(6), T(6), T(5), U(56) }, 317bf215546Sopenharmony_ci { 10, 4, L(3), U(6), U(5), T(6), T(6), T(5), EC }, 318bf215546Sopenharmony_ci { 11, 5, Z, L(3), U(7), T(7), T(7), EC, EC }, 319bf215546Sopenharmony_ci}; 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci#undef L 322bf215546Sopenharmony_ci#undef U 323bf215546Sopenharmony_ci#undef T 324bf215546Sopenharmony_ci#undef EC 325bf215546Sopenharmony_ci#undef M 326bf215546Sopenharmony_ci#undef Z 327bf215546Sopenharmony_ci#undef H 328bf215546Sopenharmony_ci#undef R 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci/* 32-bit modes for slots 2/3, as encoded in the register block. Other values 331bf215546Sopenharmony_ci * are reserved. First part specifies behaviour of slot 2 (Idle, Read, Write 332bf215546Sopenharmony_ci * Full, Write Low, Write High), second part behaviour of slot 3, and the last 333bf215546Sopenharmony_ci * part specifies the source for the write (FMA, ADD, or MIX for FMA/ADD). 334bf215546Sopenharmony_ci * 335bf215546Sopenharmony_ci * IDLE is a special mode disabling both slots, except for the first 336bf215546Sopenharmony_ci * instruction in the clause which uses IDLE_1 for the same purpose. 337bf215546Sopenharmony_ci * 338bf215546Sopenharmony_ci * All fields 0 used as sentinel for reserved encoding, so IDLE(_1) have FMA 339bf215546Sopenharmony_ci * set (and ignored) as a placeholder to differentiate from reserved. 340bf215546Sopenharmony_ci */ 341bf215546Sopenharmony_cienum bifrost_reg_mode { 342bf215546Sopenharmony_ci BIFROST_R_WL_FMA = 1, 343bf215546Sopenharmony_ci BIFROST_R_WH_FMA = 2, 344bf215546Sopenharmony_ci BIFROST_R_W_FMA = 3, 345bf215546Sopenharmony_ci BIFROST_R_WL_ADD = 4, 346bf215546Sopenharmony_ci BIFROST_R_WH_ADD = 5, 347bf215546Sopenharmony_ci BIFROST_R_W_ADD = 6, 348bf215546Sopenharmony_ci BIFROST_WL_WL_ADD = 7, 349bf215546Sopenharmony_ci BIFROST_WL_WH_ADD = 8, 350bf215546Sopenharmony_ci BIFROST_WL_W_ADD = 9, 351bf215546Sopenharmony_ci BIFROST_WH_WL_ADD = 10, 352bf215546Sopenharmony_ci BIFROST_WH_WH_ADD = 11, 353bf215546Sopenharmony_ci BIFROST_WH_W_ADD = 12, 354bf215546Sopenharmony_ci BIFROST_W_WL_ADD = 13, 355bf215546Sopenharmony_ci BIFROST_W_WH_ADD = 14, 356bf215546Sopenharmony_ci BIFROST_W_W_ADD = 15, 357bf215546Sopenharmony_ci BIFROST_IDLE_1 = 16, 358bf215546Sopenharmony_ci BIFROST_I_W_FMA = 17, 359bf215546Sopenharmony_ci BIFROST_I_WL_FMA = 18, 360bf215546Sopenharmony_ci BIFROST_I_WH_FMA = 19, 361bf215546Sopenharmony_ci BIFROST_R_I = 20, 362bf215546Sopenharmony_ci BIFROST_I_W_ADD = 21, 363bf215546Sopenharmony_ci BIFROST_I_WL_ADD = 22, 364bf215546Sopenharmony_ci BIFROST_I_WH_ADD = 23, 365bf215546Sopenharmony_ci BIFROST_WL_WH_MIX = 24, 366bf215546Sopenharmony_ci BIFROST_WH_WL_MIX = 26, 367bf215546Sopenharmony_ci BIFROST_IDLE = 27, 368bf215546Sopenharmony_ci}; 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_cienum bifrost_reg_op { 371bf215546Sopenharmony_ci BIFROST_OP_IDLE = 0, 372bf215546Sopenharmony_ci BIFROST_OP_READ = 1, 373bf215546Sopenharmony_ci BIFROST_OP_WRITE = 2, 374bf215546Sopenharmony_ci BIFROST_OP_WRITE_LO = 3, 375bf215546Sopenharmony_ci BIFROST_OP_WRITE_HI = 4, 376bf215546Sopenharmony_ci}; 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_cistruct bifrost_reg_ctrl_23 { 379bf215546Sopenharmony_ci enum bifrost_reg_op slot2; 380bf215546Sopenharmony_ci enum bifrost_reg_op slot3; 381bf215546Sopenharmony_ci bool slot3_fma; 382bf215546Sopenharmony_ci}; 383bf215546Sopenharmony_ci 384bf215546Sopenharmony_ci#ifndef __cplusplus 385bf215546Sopenharmony_cistatic const struct bifrost_reg_ctrl_23 bifrost_reg_ctrl_lut[32] = { 386bf215546Sopenharmony_ci [BIFROST_R_WL_FMA] = { BIFROST_OP_READ, BIFROST_OP_WRITE_LO, true }, 387bf215546Sopenharmony_ci [BIFROST_R_WH_FMA] = { BIFROST_OP_READ, BIFROST_OP_WRITE_HI, true }, 388bf215546Sopenharmony_ci [BIFROST_R_W_FMA] = { BIFROST_OP_READ, BIFROST_OP_WRITE, true }, 389bf215546Sopenharmony_ci [BIFROST_R_WL_ADD] = { BIFROST_OP_READ, BIFROST_OP_WRITE_LO, false }, 390bf215546Sopenharmony_ci [BIFROST_R_WH_ADD] = { BIFROST_OP_READ, BIFROST_OP_WRITE_HI, false }, 391bf215546Sopenharmony_ci [BIFROST_R_W_ADD] = { BIFROST_OP_READ, BIFROST_OP_WRITE, false }, 392bf215546Sopenharmony_ci [BIFROST_WL_WL_ADD] = { BIFROST_OP_WRITE_LO, BIFROST_OP_WRITE_LO, false }, 393bf215546Sopenharmony_ci [BIFROST_WL_WH_ADD] = { BIFROST_OP_WRITE_LO, BIFROST_OP_WRITE_HI, false }, 394bf215546Sopenharmony_ci [BIFROST_WL_W_ADD] = { BIFROST_OP_WRITE_LO, BIFROST_OP_WRITE, false }, 395bf215546Sopenharmony_ci [BIFROST_WH_WL_ADD] = { BIFROST_OP_WRITE_HI, BIFROST_OP_WRITE_LO, false }, 396bf215546Sopenharmony_ci [BIFROST_WH_WH_ADD] = { BIFROST_OP_WRITE_HI, BIFROST_OP_WRITE_HI, false }, 397bf215546Sopenharmony_ci [BIFROST_WH_W_ADD] = { BIFROST_OP_WRITE_HI, BIFROST_OP_WRITE, false }, 398bf215546Sopenharmony_ci [BIFROST_W_WL_ADD] = { BIFROST_OP_WRITE, BIFROST_OP_WRITE_LO, false }, 399bf215546Sopenharmony_ci [BIFROST_W_WH_ADD] = { BIFROST_OP_WRITE, BIFROST_OP_WRITE_HI, false }, 400bf215546Sopenharmony_ci [BIFROST_W_W_ADD] = { BIFROST_OP_WRITE, BIFROST_OP_WRITE, false }, 401bf215546Sopenharmony_ci [BIFROST_IDLE_1] = { BIFROST_OP_IDLE, BIFROST_OP_IDLE, true }, 402bf215546Sopenharmony_ci [BIFROST_I_W_FMA] = { BIFROST_OP_IDLE, BIFROST_OP_WRITE, true }, 403bf215546Sopenharmony_ci [BIFROST_I_WL_FMA] = { BIFROST_OP_IDLE, BIFROST_OP_WRITE_LO, true }, 404bf215546Sopenharmony_ci [BIFROST_I_WH_FMA] = { BIFROST_OP_IDLE, BIFROST_OP_WRITE_HI, true }, 405bf215546Sopenharmony_ci [BIFROST_R_I] = { BIFROST_OP_READ, BIFROST_OP_IDLE, false }, 406bf215546Sopenharmony_ci [BIFROST_I_W_ADD] = { BIFROST_OP_IDLE, BIFROST_OP_WRITE, false }, 407bf215546Sopenharmony_ci [BIFROST_I_WL_ADD] = { BIFROST_OP_IDLE, BIFROST_OP_WRITE_LO, false }, 408bf215546Sopenharmony_ci [BIFROST_I_WH_ADD] = { BIFROST_OP_IDLE, BIFROST_OP_WRITE_HI, false }, 409bf215546Sopenharmony_ci [BIFROST_WL_WH_MIX] = { BIFROST_OP_WRITE_LO, BIFROST_OP_WRITE_HI, false }, 410bf215546Sopenharmony_ci [BIFROST_WH_WL_MIX] = { BIFROST_OP_WRITE_HI, BIFROST_OP_WRITE_LO, false }, 411bf215546Sopenharmony_ci [BIFROST_IDLE] = { BIFROST_OP_IDLE, BIFROST_OP_IDLE, true }, 412bf215546Sopenharmony_ci}; 413bf215546Sopenharmony_ci#endif 414bf215546Sopenharmony_ci 415bf215546Sopenharmony_ci/* Texture operator descriptors in various states. Usually packed in the 416bf215546Sopenharmony_ci * compiler and stored as a constant */ 417bf215546Sopenharmony_ci 418bf215546Sopenharmony_cienum bifrost_texture_operation_mode { 419bf215546Sopenharmony_ci /* Dual texturing */ 420bf215546Sopenharmony_ci BIFROST_TEXTURE_OPERATION_DUAL = 1, 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_ci /* Single texturing */ 423bf215546Sopenharmony_ci BIFROST_TEXTURE_OPERATION_SINGLE = 3, 424bf215546Sopenharmony_ci}; 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_cienum bifrost_index { 427bf215546Sopenharmony_ci /* Both texture/sampler index immediate */ 428bf215546Sopenharmony_ci BIFROST_INDEX_IMMEDIATE_SHARED = 0, 429bf215546Sopenharmony_ci 430bf215546Sopenharmony_ci /* Sampler index immediate, texture index from staging */ 431bf215546Sopenharmony_ci BIFROST_INDEX_IMMEDIATE_SAMPLER = 1, 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_ci /* Texture index immediate, sampler index from staging */ 434bf215546Sopenharmony_ci BIFROST_INDEX_IMMEDIATE_TEXTURE = 2, 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_ci /* Both indices from (separate) staging registers */ 437bf215546Sopenharmony_ci BIFROST_INDEX_REGISTER = 3, 438bf215546Sopenharmony_ci}; 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_cienum bifrost_tex_op { 441bf215546Sopenharmony_ci /* Given explicit derivatives, compute a gradient descriptor */ 442bf215546Sopenharmony_ci BIFROST_TEX_OP_GRDESC_DER = 4, 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci /* Given implicit derivatives (texture coordinates in a fragment 445bf215546Sopenharmony_ci * shader), compute a gradient descriptor */ 446bf215546Sopenharmony_ci BIFROST_TEX_OP_GRDESC = 5, 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci /* Fetch a texel. Takes a staging register with LOD level / face index 449bf215546Sopenharmony_ci * packed 16:16 */ 450bf215546Sopenharmony_ci BIFROST_TEX_OP_FETCH = 6, 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_ci /* Filtered texture */ 453bf215546Sopenharmony_ci BIFROST_TEX_OP_TEX = 7, 454bf215546Sopenharmony_ci}; 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_cienum bifrost_lod_mode { 457bf215546Sopenharmony_ci /* Takes two staging registers forming a 64-bit gradient descriptor 458bf215546Sopenharmony_ci * (computed by a previous GRDESC or GRDESC_DER operation) */ 459bf215546Sopenharmony_ci BIFROST_LOD_MODE_GRDESC = 3, 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_ci /* Take a staging register with 8:8 fixed-point in bottom 16-bits 462bf215546Sopenharmony_ci * specifying an explicit LOD */ 463bf215546Sopenharmony_ci BIFROST_LOD_MODE_EXPLICIT = 4, 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci /* Takes a staging register with bottom 16-bits as 8:8 fixed-point LOD 466bf215546Sopenharmony_ci * bias and top 16-bit as 8:8 fixed-point lower bound (generally left 467bf215546Sopenharmony_ci * zero), added and clamped to a computed LOD */ 468bf215546Sopenharmony_ci BIFROST_LOD_MODE_BIAS = 5, 469bf215546Sopenharmony_ci 470bf215546Sopenharmony_ci /* Set LOD to zero */ 471bf215546Sopenharmony_ci BIFROST_LOD_MODE_ZERO = 6, 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci /* Compute LOD */ 474bf215546Sopenharmony_ci BIFROST_LOD_MODE_COMPUTE = 7, 475bf215546Sopenharmony_ci}; 476bf215546Sopenharmony_ci 477bf215546Sopenharmony_cienum bifrost_texture_format { 478bf215546Sopenharmony_ci /* 16-bit floating point, with optional clamping */ 479bf215546Sopenharmony_ci BIFROST_TEXTURE_FORMAT_F16 = 0, 480bf215546Sopenharmony_ci BIFROST_TEXTURE_FORMAT_F16_POS = 1, 481bf215546Sopenharmony_ci BIFROST_TEXTURE_FORMAT_F16_PM1 = 2, 482bf215546Sopenharmony_ci BIFROST_TEXTURE_FORMAT_F16_1 = 3, 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci /* 32-bit floating point, with optional clamping */ 485bf215546Sopenharmony_ci BIFROST_TEXTURE_FORMAT_F32 = 4, 486bf215546Sopenharmony_ci BIFROST_TEXTURE_FORMAT_F32_POS = 5, 487bf215546Sopenharmony_ci BIFROST_TEXTURE_FORMAT_F32_PM1 = 6, 488bf215546Sopenharmony_ci BIFROST_TEXTURE_FORMAT_F32_1 = 7, 489bf215546Sopenharmony_ci}; 490bf215546Sopenharmony_ci 491bf215546Sopenharmony_cienum bifrost_texture_format_full { 492bf215546Sopenharmony_ci /* Transclude bifrost_texture_format from above */ 493bf215546Sopenharmony_ci 494bf215546Sopenharmony_ci /* Integers, unclamped */ 495bf215546Sopenharmony_ci BIFROST_TEXTURE_FORMAT_U16 = 12, 496bf215546Sopenharmony_ci BIFROST_TEXTURE_FORMAT_S16 = 13, 497bf215546Sopenharmony_ci BIFROST_TEXTURE_FORMAT_U32 = 14, 498bf215546Sopenharmony_ci BIFROST_TEXTURE_FORMAT_S32 = 15, 499bf215546Sopenharmony_ci}; 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_cienum bifrost_texture_fetch { 502bf215546Sopenharmony_ci /* Default texelFetch */ 503bf215546Sopenharmony_ci BIFROST_TEXTURE_FETCH_TEXEL = 1, 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_ci /* Deprecated, fetches 4x U32 of a U8 x 4 texture. Do not use. */ 506bf215546Sopenharmony_ci BIFROST_TEXTURE_FETCH_GATHER4_RGBA = 3, 507bf215546Sopenharmony_ci 508bf215546Sopenharmony_ci /* Gathers */ 509bf215546Sopenharmony_ci BIFROST_TEXTURE_FETCH_GATHER4_R = 4, 510bf215546Sopenharmony_ci BIFROST_TEXTURE_FETCH_GATHER4_G = 5, 511bf215546Sopenharmony_ci BIFROST_TEXTURE_FETCH_GATHER4_B = 6, 512bf215546Sopenharmony_ci BIFROST_TEXTURE_FETCH_GATHER4_A = 7 513bf215546Sopenharmony_ci}; 514bf215546Sopenharmony_ci 515bf215546Sopenharmony_cistruct bifrost_texture_operation { 516bf215546Sopenharmony_ci /* If immediate_indices is set: 517bf215546Sopenharmony_ci * - immediate sampler index 518bf215546Sopenharmony_ci * - index used as texture index 519bf215546Sopenharmony_ci * Otherwise: 520bf215546Sopenharmony_ci * - bifrost_single_index in lower 2 bits 521bf215546Sopenharmony_ci * - 0x3 in upper 2 bits (single-texturing) 522bf215546Sopenharmony_ci */ 523bf215546Sopenharmony_ci unsigned sampler_index_or_mode : 4; 524bf215546Sopenharmony_ci unsigned index : 7; 525bf215546Sopenharmony_ci bool immediate_indices : 1; 526bf215546Sopenharmony_ci enum bifrost_tex_op op : 3; 527bf215546Sopenharmony_ci 528bf215546Sopenharmony_ci /* If set for TEX/FETCH, loads texel offsets and multisample index from 529bf215546Sopenharmony_ci * a staging register containing offset_x:offset_y:offset_z:ms_index 530bf215546Sopenharmony_ci * packed 8:8:8:8. Offsets must be in [-31, +31]. If set for 531bf215546Sopenharmony_ci * GRDESC(_DER), disable LOD bias. */ 532bf215546Sopenharmony_ci bool offset_or_bias_disable : 1; 533bf215546Sopenharmony_ci 534bf215546Sopenharmony_ci /* If set for TEX/FETCH, loads fp32 shadow comparison value from a 535bf215546Sopenharmony_ci * staging register. Implies fetch_component = gather4_r. If set for 536bf215546Sopenharmony_ci * GRDESC(_DER), disables LOD clamping. */ 537bf215546Sopenharmony_ci bool shadow_or_clamp_disable : 1; 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci /* If set, loads an uint32 array index from a staging register. */ 540bf215546Sopenharmony_ci bool array : 1; 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_ci /* Texture dimension, or 0 for a cubemap */ 543bf215546Sopenharmony_ci unsigned dimension : 2; 544bf215546Sopenharmony_ci 545bf215546Sopenharmony_ci /* Method to compute LOD value or for a FETCH, the 546bf215546Sopenharmony_ci * bifrost_texture_fetch component specification */ 547bf215546Sopenharmony_ci enum bifrost_lod_mode lod_or_fetch : 3; 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci /* Reserved */ 550bf215546Sopenharmony_ci unsigned zero : 1; 551bf215546Sopenharmony_ci 552bf215546Sopenharmony_ci /* Register format for the result */ 553bf215546Sopenharmony_ci enum bifrost_texture_format_full format : 4; 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci /* Write mask for the result */ 556bf215546Sopenharmony_ci unsigned mask : 4; 557bf215546Sopenharmony_ci} __attribute__((packed)); 558bf215546Sopenharmony_ci 559bf215546Sopenharmony_cistruct bifrost_dual_texture_operation { 560bf215546Sopenharmony_ci unsigned primary_sampler_index : 2; 561bf215546Sopenharmony_ci unsigned mode : 2; /* 0x1 for dual */ 562bf215546Sopenharmony_ci unsigned primary_texture_index : 2; 563bf215546Sopenharmony_ci unsigned secondary_sampler_index : 2; 564bf215546Sopenharmony_ci unsigned secondary_texture_index : 2; 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci /* Leave zero for dual texturing */ 567bf215546Sopenharmony_ci unsigned reserved : 1; 568bf215546Sopenharmony_ci unsigned index_mode_zero : 1; 569bf215546Sopenharmony_ci 570bf215546Sopenharmony_ci /* Base staging register to write the secondary results to */ 571bf215546Sopenharmony_ci unsigned secondary_register : 6; 572bf215546Sopenharmony_ci 573bf215546Sopenharmony_ci /* Format/mask for each texture */ 574bf215546Sopenharmony_ci enum bifrost_texture_format secondary_format : 3; 575bf215546Sopenharmony_ci unsigned secondary_mask : 4; 576bf215546Sopenharmony_ci 577bf215546Sopenharmony_ci enum bifrost_texture_format primary_format : 3; 578bf215546Sopenharmony_ci unsigned primary_mask : 4; 579bf215546Sopenharmony_ci} __attribute__((packed)); 580bf215546Sopenharmony_ci 581bf215546Sopenharmony_cistatic inline uint32_t 582bf215546Sopenharmony_cibi_dual_tex_as_u32(struct bifrost_dual_texture_operation desc) 583bf215546Sopenharmony_ci{ 584bf215546Sopenharmony_ci uint32_t desc_u; 585bf215546Sopenharmony_ci memcpy(&desc_u, &desc, sizeof(desc)); 586bf215546Sopenharmony_ci 587bf215546Sopenharmony_ci return desc_u; 588bf215546Sopenharmony_ci} 589bf215546Sopenharmony_ci 590bf215546Sopenharmony_ci#define BIFROST_MEGA_SAMPLE 128 591bf215546Sopenharmony_ci#define BIFROST_ALL_SAMPLES 255 592bf215546Sopenharmony_ci#define BIFROST_CURRENT_PIXEL 255 593bf215546Sopenharmony_ci 594bf215546Sopenharmony_cistruct bifrost_pixel_indices { 595bf215546Sopenharmony_ci unsigned sample : 8; 596bf215546Sopenharmony_ci unsigned rt : 8; 597bf215546Sopenharmony_ci unsigned x : 8; 598bf215546Sopenharmony_ci unsigned y : 8; 599bf215546Sopenharmony_ci} __attribute__((packed)); 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_cienum bi_constmod { 602bf215546Sopenharmony_ci BI_CONSTMOD_NONE, 603bf215546Sopenharmony_ci BI_CONSTMOD_PC_LO, 604bf215546Sopenharmony_ci BI_CONSTMOD_PC_HI, 605bf215546Sopenharmony_ci BI_CONSTMOD_PC_LO_HI 606bf215546Sopenharmony_ci}; 607bf215546Sopenharmony_ci 608bf215546Sopenharmony_cistruct bi_constants { 609bf215546Sopenharmony_ci /* Raw constant values */ 610bf215546Sopenharmony_ci uint64_t raw[6]; 611bf215546Sopenharmony_ci 612bf215546Sopenharmony_ci /* Associated modifier derived from M values */ 613bf215546Sopenharmony_ci enum bi_constmod mods[6]; 614bf215546Sopenharmony_ci}; 615bf215546Sopenharmony_ci 616bf215546Sopenharmony_ci/* FAU selectors for constants are out-of-order, construct the top bits 617bf215546Sopenharmony_ci * here given a embedded constant index in a clause */ 618bf215546Sopenharmony_ci 619bf215546Sopenharmony_cistatic inline unsigned 620bf215546Sopenharmony_cibi_constant_field(unsigned idx) 621bf215546Sopenharmony_ci{ 622bf215546Sopenharmony_ci const unsigned values[] = { 623bf215546Sopenharmony_ci 4, 5, 6, 7, 2, 3 624bf215546Sopenharmony_ci }; 625bf215546Sopenharmony_ci 626bf215546Sopenharmony_ci assert(idx <= 5); 627bf215546Sopenharmony_ci return values[idx] << 4; 628bf215546Sopenharmony_ci} 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_ci#ifdef __cplusplus 631bf215546Sopenharmony_ci} /* extern C */ 632bf215546Sopenharmony_ci#endif 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_ci#endif 635