1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2017 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SkJumper_misc_DEFINED 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define SkJumper_misc_DEFINED 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <string.h> // for memcpy() 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Miscellany used by SkJumper_stages.cpp and SkJumper_stages_lowp.cpp. 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Every function in this file should be marked static and inline using SI. 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if defined(__clang__) 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot #define SI __attribute__((always_inline)) static inline 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#else 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot #define SI static inline 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T, typename P> 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSI T unaligned_load(const P* p) { // const void* would work too, but const P* helps ARMv7 codegen. 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot T v; 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memcpy(&v, p, sizeof(v)); 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return v; 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T, typename P> 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSI void unaligned_store(P* p, T v) { 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memcpy(p, &v, sizeof(v)); 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename Dst, typename Src> 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSI Dst bit_cast(const Src& src) { 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static_assert(sizeof(Dst) == sizeof(Src), ""); 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return unaligned_load<Dst>(&src); 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename Dst, typename Src> 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSI Dst widen_cast(const Src& src) { 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static_assert(sizeof(Dst) > sizeof(Src), ""); 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Dst dst; 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memcpy(&dst, &src, sizeof(Src)); 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return dst; 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Our program is an array of void*, either 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// - 1 void* per stage with no context pointer, the next stage; 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// - 2 void* per stage with a context pointer, first the context pointer, then the next stage. 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// load_and_inc() steps the program forward by 1 void*, returning that pointer. 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSI void* load_and_inc(void**& program) { 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if defined(__GNUC__) && defined(__x86_64__) 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If program is in %rsi (we try to make this likely) then this is a single instruction. 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void* rax; 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot asm("lodsq" : "=a"(rax), "+S"(program)); // Write-only %rax, read-write %rsi. 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return rax; 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#else 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // On ARM *program++ compiles into pretty ideal code without any handholding. 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return *program++; 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Lazily resolved on first cast. Does nothing if cast to Ctx::None. 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct Ctx { 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot struct None {}; 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void* ptr; 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void**& program; 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot explicit Ctx(void**& p) : ptr(nullptr), program(p) {} 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot template <typename T> 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot operator T*() { 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!ptr) { ptr = load_and_inc(program); } 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return (T*)ptr; 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot operator None() { return None{}; } 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif//SkJumper_misc_DEFINED 84