Path: blob/a-new-beginning/SharedDependencies/Sources/nihstro/assembler.cpp
2 views
// Copyright 2014 Tony Wasserka1// All rights reserved.2//3// Redistribution and use in source and binary forms, with or without4// modification, are permitted provided that the following conditions are met:5//6// * Redistributions of source code must retain the above copyright7// notice, this list of conditions and the following disclaimer.8// * Redistributions in binary form must reproduce the above copyright9// notice, this list of conditions and the following disclaimer in the10// documentation and/or other materials provided with the distribution.11// * Neither the name of the owner nor the names of its contributors may12// be used to endorse or promote products derived from this software13// without specific prior written permission.14//15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS16// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT17// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR18// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT19// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT21// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.2627#include <string>28#include <iostream>29#include <sstream>30#include <fstream>3132#include <stack>3334#include <boost/version.hpp>35#include <boost/program_options.hpp>36#include <boost/range/adaptor/reversed.hpp>37#include <boost/range/adaptor/sliced.hpp>38#include <boost/range/algorithm/count_if.hpp>3940#if BOOST_VERSION >= 10840041#include <boost/core/invoke_swap.hpp>42#endif4344#include "nihstro/parser_assembly.h"45#include "nihstro/preprocessor.h"46#include "nihstro/source_tree.h"4748#include "nihstro/shader_binary.h"49#include "nihstro/shader_bytecode.h"5051#include "nihstro/float24.h"5253using namespace nihstro;5455enum class RegisterSpace : int {56Input = 0,57Temporary = 0x10,58FloatUniform = 0x20,59Output = 0x80,60Address = 0x90,61AddressEnd = 0x92,62ConditionalCode = 0x93,63IntUniform = 0x94,64BoolUniform = 0x98,6566Max = BoolUniform + 15,67};6869// Smallest unit an expression evaluates to:70// Index to register + number of components + swizzle mask + sign71// Labels are different.72struct Atomic {73int register_index; // TODO: Change type to RegisterSpace74InputSwizzlerMask mask;75bool negate;76int relative_address_source;7778const RegisterType GetType() const {79if (register_index >= (int)RegisterSpace::BoolUniform)80return RegisterType::BoolUniform;81else if (register_index >= (int)RegisterSpace::IntUniform)82return RegisterType::IntUniform;83else if (register_index >= (int)RegisterSpace::ConditionalCode)84return RegisterType::ConditionalCode;85else if (register_index >= (int)RegisterSpace::Address)86return RegisterType::Address;87else if (register_index >= (int)RegisterSpace::Output)88return RegisterType::Output;89else if (register_index >= (int)RegisterSpace::FloatUniform)90return RegisterType::FloatUniform;91else if (register_index >= (int)RegisterSpace::Temporary)92return RegisterType::Temporary;93else if (register_index >= (int)RegisterSpace::Input)94return RegisterType::Input;95else96assert(0);97return {};98}99100int GetIndex() const {101if (register_index >= (int)RegisterSpace::BoolUniform)102return register_index - (int)RegisterSpace::BoolUniform;103else if (register_index >= (int)RegisterSpace::IntUniform)104return register_index - (int)RegisterSpace::IntUniform;105else if (register_index >= (int)RegisterSpace::ConditionalCode)106return register_index - (int)RegisterSpace::ConditionalCode;107else if (register_index >= (int)RegisterSpace::Address)108return register_index - (int)RegisterSpace::Address;109else if (register_index >= (int)RegisterSpace::Output)110return register_index - (int)RegisterSpace::Output;111else if (register_index >= (int)RegisterSpace::FloatUniform)112return register_index - (int)RegisterSpace::FloatUniform;113else if (register_index >= (int)RegisterSpace::Temporary)114return register_index - (int)RegisterSpace::Temporary;115else if (register_index >= (int)RegisterSpace::Input)116return register_index - (int)RegisterSpace::Input;117else118assert(0);119return {};120}121122// Returns whether this is a float uniform register OR uses relative addressing123bool IsExtended() const {124return GetType() == RegisterType::FloatUniform ||125relative_address_source != 0;126}127};128129struct DestSwizzlerMask {130DestSwizzlerMask(const InputSwizzlerMask& input) {131std::fill(component_set, &component_set[4], false);132for (InputSwizzlerMask::Component comp : {InputSwizzlerMask::x, InputSwizzlerMask::y,133InputSwizzlerMask::z, InputSwizzlerMask::w}) {134for (int i = 0; i < input.num_components; ++i) {135if (comp == input.components[i]) {136component_set[comp] = true;137}138}139}140}141142bool component_set[4];143};144145struct SourceSwizzlerMask {146147// Generate source mask according to the layout given by the destination mask148// E.g. the source swizzle pattern used by the instruction "mov o0.zw, t0.xy" will149// be {(undefined),(undefined),x,y} rather than {x,y,(undefined),(undefined)}.150static SourceSwizzlerMask AccordingToDestMask(const InputSwizzlerMask& input, const DestSwizzlerMask& dest) {151SourceSwizzlerMask ret = {Unspecified, Unspecified, Unspecified, Unspecified };152153int active_component = 0;154for (int i = 0; i < 4; ++i)155if (dest.component_set[i])156ret.components[i] = static_cast<Component>(input.components[active_component++]);157158return ret;159}160161static SourceSwizzlerMask Expand(const InputSwizzlerMask& input) {162SourceSwizzlerMask ret = {Unspecified, Unspecified, Unspecified, Unspecified };163164for (int i = 0; i < input.num_components; ++i)165ret.components[i] = static_cast<Component>(input.components[i]);166167return ret;168}169170enum Component : uint8_t {171x = 0,172y = 1,173z = 2,174w = 3,175Unspecified176};177Component components[4];178};179180static InputSwizzlerMask MergeSwizzleMasks(const InputSwizzlerMask& inner_mask, const InputSwizzlerMask& outer_mask) {181// TODO: Error out if the swizzle masks can't actually be merged..182183auto contains_component = [](const InputSwizzlerMask& swizzle_mask,const nihstro::InputSwizzlerMask::Component &c) -> bool {184for (auto &comp : swizzle_mask.components) {185if (comp == c)186return true;187}188189return false;190};191192for (const InputSwizzlerMask::Component &c : outer_mask.components) {193if (!contains_component(inner_mask, c))194throw "Attempt to access component " + to_string(c) + " in vector " + to_string(inner_mask);195}196197InputSwizzlerMask out;198out.num_components = outer_mask.num_components;199for (int comp = 0; comp < outer_mask.num_components; ++comp) {200out.components[comp] = inner_mask.components[outer_mask.components[comp]];201}202203return out;204}205206static std::map<std::string, Atomic> identifier_table;207208static Atomic& LookupIdentifier(const std::string& name) {209auto it = identifier_table.find(name);210if (it == identifier_table.end())211throw "Unknown identifier \"" + name + "\"";212213return it->second;214}215216// Evaluate expression to a particular Atomic217static Atomic EvaluateExpression(const Expression& expr) {218Atomic ret = LookupIdentifier(expr.GetIdentifier());219220ret.negate = expr.GetSign() == -1;221ret.relative_address_source = 0;222223bool relative_address_set = false;224if (expr.HasIndexExpression()) {225const auto& array_index_expression = expr.GetIndexExpression();226int index = 0;227for (int i = 0; i < array_index_expression.GetCount(); ++i) {228if (array_index_expression.IsRawIndex(i)) {229index += array_index_expression.GetRawIndex(i);230} else if (array_index_expression.IsAddressRegisterIdentifier(i)) {231if (relative_address_set) {232throw "May not use more than one register in relative addressing";233}234235ret.relative_address_source = LookupIdentifier(array_index_expression.GetAddressRegisterIdentifier(i)).register_index;236if (ret.relative_address_source < (int)RegisterSpace::Address ||237ret.relative_address_source > (int)RegisterSpace::AddressEnd) {238throw "Invalid register " + array_index_expression.GetAddressRegisterIdentifier(i)+ " (" + std::to_string(ret.relative_address_source) + ") used for relative addressing (only a0, a1 and lcnt are valid indexes)";239}240ret.relative_address_source -= (int)RegisterSpace::Address - 1; // 0 is reserved for "no dynamic indexing", hence the first address register gets value 1241relative_address_set = true;242}243}244ret.register_index += index;245}246// Apply swizzle mask(s)247for (const auto& swizzle_mask : expr.GetSwizzleMasks())248ret.mask = MergeSwizzleMasks(ret.mask, swizzle_mask);249250return ret;251};252253// TODO: Provide optimized versions for functions without src2254static size_t FindOrAddSwizzlePattern(std::vector<SwizzlePattern>& swizzle_patterns,255const DestSwizzlerMask& dest_mask,256const SourceSwizzlerMask& mask_src1,257const SourceSwizzlerMask& mask_src2,258const SourceSwizzlerMask& mask_src3,259bool negate_src1, bool negate_src2, bool negate_src3) {260SwizzlePattern swizzle_pattern;261swizzle_pattern.hex = 0;262263for (int i = 0, active_component = 0; i < 4; ++i) {264if (dest_mask.component_set[i])265swizzle_pattern.SetDestComponentEnabled(i, true);266267if (mask_src1.components[i] != SourceSwizzlerMask::Unspecified)268swizzle_pattern.SetSelectorSrc1(i, static_cast<SwizzlePattern::Selector>(mask_src1.components[i]));269270if (mask_src2.components[i] != SourceSwizzlerMask::Unspecified)271swizzle_pattern.SetSelectorSrc2(i, static_cast<SwizzlePattern::Selector>(mask_src2.components[i]));272273if (mask_src3.components[i] != SourceSwizzlerMask::Unspecified)274swizzle_pattern.SetSelectorSrc3(i, static_cast<SwizzlePattern::Selector>(mask_src3.components[i]));275}276277swizzle_pattern.negate_src1 = negate_src1;278swizzle_pattern.negate_src2 = negate_src2;279swizzle_pattern.negate_src3 = negate_src3;280281auto it = std::find_if(swizzle_patterns.begin(), swizzle_patterns.end(),282[&swizzle_pattern](const SwizzlePattern& val) { return val.hex == swizzle_pattern.hex; });283if (it == swizzle_patterns.end()) {284swizzle_patterns.push_back(swizzle_pattern);285it = swizzle_patterns.end() - 1;286287if (swizzle_patterns.size() > 127)288throw "Limit of 127 swizzle patterns has been exhausted";289}290291return it - swizzle_patterns.begin();292};293294static size_t FindOrAddSwizzlePattern(std::vector<SwizzlePattern>& swizzle_patterns,295const DestSwizzlerMask& dest_mask,296const SourceSwizzlerMask& mask_src1,297const SourceSwizzlerMask& mask_src2,298bool negate_src1, bool negate_src2) {299SwizzlePattern swizzle_pattern;300swizzle_pattern.hex = 0;301302for (int i = 0, active_component = 0; i < 4; ++i) {303if (dest_mask.component_set[i])304swizzle_pattern.SetDestComponentEnabled(i, true);305306if (mask_src1.components[i] != SourceSwizzlerMask::Unspecified)307swizzle_pattern.SetSelectorSrc1(i, static_cast<SwizzlePattern::Selector>(mask_src1.components[i]));308309if (mask_src2.components[i] != SourceSwizzlerMask::Unspecified)310swizzle_pattern.SetSelectorSrc2(i, static_cast<SwizzlePattern::Selector>(mask_src2.components[i]));311}312313swizzle_pattern.negate_src1 = negate_src1;314swizzle_pattern.negate_src2 = negate_src2;315316auto it = std::find_if(swizzle_patterns.begin(), swizzle_patterns.end(),317[&swizzle_pattern](const SwizzlePattern& val) { return val.hex == swizzle_pattern.hex; });318if (it == swizzle_patterns.end()) {319swizzle_patterns.push_back(swizzle_pattern);320it = swizzle_patterns.end() - 1;321322if (swizzle_patterns.size() > 127)323throw "Limit of 127 swizzle patterns has been exhausted";324}325326return it - swizzle_patterns.begin();327};328329static size_t FindOrAddSwizzlePattern(std::vector<SwizzlePattern>& swizzle_patterns,330const SourceSwizzlerMask& mask_src1,331const SourceSwizzlerMask& mask_src2,332bool negate_src1, bool negate_src2) {333SwizzlePattern swizzle_pattern;334swizzle_pattern.hex = 0;335336for (int i = 0, active_component = 0; i < 4; ++i) {337if (mask_src1.components[i] != SourceSwizzlerMask::Unspecified)338swizzle_pattern.SetSelectorSrc1(i, static_cast<SwizzlePattern::Selector>(mask_src1.components[i]));339340if (mask_src2.components[i] != SourceSwizzlerMask::Unspecified)341swizzle_pattern.SetSelectorSrc2(i, static_cast<SwizzlePattern::Selector>(mask_src2.components[i]));342}343344swizzle_pattern.negate_src1 = negate_src1;345swizzle_pattern.negate_src2 = negate_src2;346347auto it = std::find_if(swizzle_patterns.begin(), swizzle_patterns.end(),348[&swizzle_pattern](const SwizzlePattern& val) { return val.hex == swizzle_pattern.hex; });349if (it == swizzle_patterns.end()) {350swizzle_patterns.push_back(swizzle_pattern);351it = swizzle_patterns.end() - 1;352353if (swizzle_patterns.size() > 127)354throw "Limit of 127 swizzle patterns has been exhausted";355}356357return it - swizzle_patterns.begin();358};359360static size_t FindOrAddSwizzlePattern(std::vector<SwizzlePattern>& swizzle_patterns,361const SourceSwizzlerMask& mask_src1,362bool negate_src1) {363SwizzlePattern swizzle_pattern;364swizzle_pattern.hex = 0;365366for (int i = 0, active_component = 0; i < 4; ++i) {367if (mask_src1.components[i] != SourceSwizzlerMask::Unspecified)368swizzle_pattern.SetSelectorSrc1(i, static_cast<SwizzlePattern::Selector>(mask_src1.components[i]));369}370371swizzle_pattern.negate_src1 = negate_src1;372373auto it = std::find_if(swizzle_patterns.begin(), swizzle_patterns.end(),374[&swizzle_pattern](const SwizzlePattern& val) { return val.hex == swizzle_pattern.hex; });375if (it == swizzle_patterns.end()) {376swizzle_patterns.push_back(swizzle_pattern);377it = swizzle_patterns.end() - 1;378379if (swizzle_patterns.size() > 127)380throw "Limit of 127 swizzle patterns has been exhausted";381}382383return it - swizzle_patterns.begin();384};385386387