diff --git a/src/panfrost/.clang-format b/src/panfrost/.clang-format index 44d043dcb6e..e93f6682233 100644 --- a/src/panfrost/.clang-format +++ b/src/panfrost/.clang-format @@ -44,6 +44,7 @@ ForEachMacros: [ 'cs_exception_handler_def', 'cs_if', 'cs_match', + 'cs_single_link_list_for_each_from', 'cs_update_compute_ctx', 'cs_update_frag_ctx', 'cs_update_progress_seqno', diff --git a/src/panfrost/genxml/cs_builder.h b/src/panfrost/genxml/cs_builder.h index a5f0e35f16f..89b63c14db9 100644 --- a/src/panfrost/genxml/cs_builder.h +++ b/src/panfrost/genxml/cs_builder.h @@ -1439,6 +1439,15 @@ cs_patch_maybe(struct cs_builder *b, struct cs_maybe *maybe) } } +struct cs_single_link_list_node { + uint64_t next; +}; + +struct cs_single_link_list { + uint64_t head; + uint64_t tail; +}; + /* Pseudoinstructions follow */ static inline void @@ -2585,6 +2594,55 @@ cs_trace_run_compute_indirect(struct cs_builder *b, cs_flush_stores(b); } +#define cs_single_link_list_for_each_from(b, current, node_type, base_name) \ + cs_while(b, MALI_CS_CONDITION_NEQUAL, current) \ + for (bool done = false; !done; \ + cs_load64_to(b, current, current, \ + offsetof(node_type, base_name.next)), \ + done = true) + +/** + * Append an item to a cs_single_link_list. + * + * @param b The current cs_builder. + * @param list_base CS register with the base address for the list pointer. + * @param list_offset Offset added to list_base. + * @param new_node_gpu GPU address of the node to insert. + * @param base_offset Offset of cs_single_link_list_node in the new node. + * @param head_tail Temporary register pair used in the function. + */ +static inline void +cs_single_link_list_add_tail(struct cs_builder *b, struct cs_index list_base, + int list_offset, struct cs_index new_node_gpu, + int base_offset, struct cs_index head_tail) +{ + assert(head_tail.size == 4); + assert(head_tail.reg % 2 == 0); + + STATIC_ASSERT(offsetof(struct cs_single_link_list, tail) == + offsetof(struct cs_single_link_list, head) + sizeof(uint64_t)); + struct cs_index head = cs_reg64(b, head_tail.reg); + struct cs_index tail = cs_reg64(b, head_tail.reg + 2); + + /* Offset of the next pointer inside the node pointed to by new_node_gpu. */ + const int offset_next = + base_offset + offsetof(struct cs_single_link_list_node, next); + + STATIC_ASSERT(offsetof(struct cs_single_link_list, head) == 0); + cs_load_to(b, head_tail, list_base, BITFIELD_MASK(4), list_offset); + + /* If the list is empty (head == NULL), set the head, otherwise append to the + * last node. */ + cs_if(b, MALI_CS_CONDITION_EQUAL, head) + cs_add64(b, head, new_node_gpu, 0); + cs_else(b) + cs_store64(b, new_node_gpu, tail, offset_next); + + cs_add64(b, tail, new_node_gpu, 0); + cs_store(b, head_tail, list_base, BITFIELD_MASK(4), list_offset); + cs_flush_stores(b); +} + #ifdef __cplusplus } #endif