1b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein/* 2b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein * Copyright 2017 Google Inc. 3b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein * 4b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein * Use of this source code is governed by a BSD-style license that can be 5b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein * found in the LICENSE file. 6b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein */ 7b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein 8b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein#ifndef SkJumper_misc_DEFINED 9b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein#define SkJumper_misc_DEFINED 10b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein 11376fd31ad485c3df35d934c56364ff0c34eacdfaMike Klein#include <string.h> // for memcpy() 12b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein 13adc78d52024fc546df61aff091a0d522a8fb95f2Mike Klein// Miscellany used by SkJumper_stages.cpp and SkJumper_stages_lowp.cpp. 14b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein 15b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein// Every function in this file should be marked static and inline using SI. 16be22636c3d9e8d73dd408c241c183e923e149574Mike Klein#if defined(__clang__) 174de1304297d7220b223c829bf386f97815db1654Herb Derby #define SI __attribute__((always_inline)) static inline 184de1304297d7220b223c829bf386f97815db1654Herb Derby#else 194de1304297d7220b223c829bf386f97815db1654Herb Derby #define SI static inline 204de1304297d7220b223c829bf386f97815db1654Herb Derby#endif 214de1304297d7220b223c829bf386f97815db1654Herb Derby 22b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein 23b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Kleintemplate <typename T, typename P> 24b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike KleinSI T unaligned_load(const P* p) { // const void* would work too, but const P* helps ARMv7 codegen. 25b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein T v; 26b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein memcpy(&v, p, sizeof(v)); 27b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein return v; 28b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein} 29b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein 30c33aa9090cd62bd1ea8dd89f9f7c9954e067a1f7Mike Kleintemplate <typename T, typename P> 31c33aa9090cd62bd1ea8dd89f9f7c9954e067a1f7Mike KleinSI void unaligned_store(P* p, T v) { 32c33aa9090cd62bd1ea8dd89f9f7c9954e067a1f7Mike Klein memcpy(p, &v, sizeof(v)); 33c33aa9090cd62bd1ea8dd89f9f7c9954e067a1f7Mike Klein} 34c33aa9090cd62bd1ea8dd89f9f7c9954e067a1f7Mike Klein 35b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Kleintemplate <typename Dst, typename Src> 36b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike KleinSI Dst bit_cast(const Src& src) { 37b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein static_assert(sizeof(Dst) == sizeof(Src), ""); 38b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein return unaligned_load<Dst>(&src); 39b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein} 40b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein 4195f53be0059940da50d4fce10da5c4dcf037b6aeMike Kleintemplate <typename Dst, typename Src> 4295f53be0059940da50d4fce10da5c4dcf037b6aeMike KleinSI Dst widen_cast(const Src& src) { 4395f53be0059940da50d4fce10da5c4dcf037b6aeMike Klein static_assert(sizeof(Dst) > sizeof(Src), ""); 4495f53be0059940da50d4fce10da5c4dcf037b6aeMike Klein Dst dst; 4595f53be0059940da50d4fce10da5c4dcf037b6aeMike Klein memcpy(&dst, &src, sizeof(Src)); 4695f53be0059940da50d4fce10da5c4dcf037b6aeMike Klein return dst; 4795f53be0059940da50d4fce10da5c4dcf037b6aeMike Klein} 4895f53be0059940da50d4fce10da5c4dcf037b6aeMike Klein 490d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein// Our program is an array of void*, either 500d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein// - 1 void* per stage with no context pointer, the next stage; 510d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein// - 2 void* per stage with a context pointer, first the context pointer, then the next stage. 520d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein 530d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein// load_and_inc() steps the program forward by 1 void*, returning that pointer. 540d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike KleinSI void* load_and_inc(void**& program) { 550d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein#if defined(__GNUC__) && defined(__x86_64__) 560d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein // If program is in %rsi (we try to make this likely) then this is a single instruction. 570d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein void* rax; 580d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein asm("lodsq" : "=a"(rax), "+S"(program)); // Write-only %rax, read-write %rsi. 590d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein return rax; 600d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein#else 610d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein // On ARM *program++ compiles into pretty ideal code without any handholding. 620d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein return *program++; 630d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein#endif 640d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein} 650d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein 667c55726156a6b2bda10035188be0077848bd3edeMike Klein// Lazily resolved on first cast. Does nothing if cast to Ctx::None. 677c55726156a6b2bda10035188be0077848bd3edeMike Kleinstruct Ctx { 68f7729c262076b88b2635e7f8d09e7f3340eea79bMike Klein struct None {}; 697c55726156a6b2bda10035188be0077848bd3edeMike Klein 700d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein void* ptr; 710d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein void**& program; 720d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein 737c55726156a6b2bda10035188be0077848bd3edeMike Klein explicit Ctx(void**& p) : ptr(nullptr), program(p) {} 740d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein 750d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein template <typename T> 760d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein operator T*() { 770d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein if (!ptr) { ptr = load_and_inc(program); } 780d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein return (T*)ptr; 790d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein } 80f7729c262076b88b2635e7f8d09e7f3340eea79bMike Klein operator None() { return None{}; } 810d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein}; 820d93010c98e8c6e50c6a0f4d8b16ada5dede81abMike Klein 83b9c4a6fc7de252633f16d11c2df10ee6de16af03Mike Klein#endif//SkJumper_misc_DEFINED 84