1 // Copyright 2009 Dolphin Emulator Project 2 // Copyright 2005 Duddie 3 // Licensed under GPLv2+ 4 // Refer to the license.txt file included. 5 6 #pragma once 7 8 #include <cstddef> 9 #include <map> 10 #include <string> 11 #include <vector> 12 13 #include "Common/CommonTypes.h" 14 15 #include "Core/DSP/DSPDisassembler.h" 16 #include "Core/DSP/DSPTables.h" 17 #include "Core/DSP/LabelMap.h" 18 19 namespace DSP 20 { 21 enum class AssemblerError 22 { 23 OK, 24 Unknown, 25 UnknownOpcode, 26 NotEnoughParameters, 27 TooManyParameters, 28 WrongParameter, 29 ExpectedParamStr, 30 ExpectedParamVal, 31 ExpectedParamReg, 32 ExpectedParamMem, 33 ExpectedParamImm, 34 IncorrectBinary, 35 IncorrectHex, 36 IncorrectDecimal, 37 LabelAlreadyExists, 38 UnknownLabel, 39 NoMatchingBrackets, 40 CantExtendOpcode, 41 ExtensionParamsOnNonExtendableOpcode, 42 WrongParameterExpectedAccumulator, 43 WrongParameterExpectedMidAccumulator, 44 InvalidRegister, 45 NumberOutOfRange, 46 PCOutOfRange, 47 }; 48 49 // Unless you want labels to carry over between files, you probably 50 // want to create a new DSPAssembler for every file you assemble. 51 class DSPAssembler 52 { 53 public: 54 explicit DSPAssembler(const AssemblerSettings& settings); 55 ~DSPAssembler(); 56 57 // line_numbers is optional (and not yet implemented). It'll receieve a list of ints, 58 // one for each word of code, indicating the source assembler code line number it came from. 59 60 // If returns false, call GetErrorString to get some text to present to the user. 61 bool Assemble(const std::string& text, std::vector<u16>& code, 62 std::vector<int>* line_numbers = nullptr); 63 GetErrorString()64 std::string GetErrorString() const { return m_last_error_str; } GetError()65 AssemblerError GetError() const { return m_last_error; } 66 67 private: 68 struct param_t 69 { 70 u32 val; 71 partype_t type; 72 char* str; 73 }; 74 75 enum segment_t 76 { 77 SEGMENT_CODE = 0, 78 SEGMENT_DATA, 79 SEGMENT_OVERLAY, 80 SEGMENT_MAX 81 }; 82 83 enum class OpcodeType 84 { 85 Primary, 86 Extension 87 }; 88 89 // Utility functions 90 s32 ParseValue(const char* str); 91 u32 ParseExpression(const char* ptr); 92 93 u32 GetParams(char* parstr, param_t* par); 94 95 void InitPass(int pass); 96 bool AssemblePass(const std::string& text, int pass); 97 98 void ShowError(AssemblerError err_code, const char* extra_info = nullptr); 99 100 char* FindBrackets(char* src, char* dst); 101 const DSPOPCTemplate* FindOpcode(std::string name, size_t par_count, OpcodeType type); 102 bool VerifyParams(const DSPOPCTemplate* opc, param_t* par, size_t count, OpcodeType type); 103 void BuildCode(const DSPOPCTemplate* opc, param_t* par, u32 par_count, u16* outbuf); 104 105 std::vector<u16> m_output_buffer; 106 107 std::string m_include_dir; 108 std::string m_cur_line; 109 110 u32 m_cur_addr = 0; 111 int m_total_size = 0; 112 u8 m_cur_pass = 0; 113 114 LabelMap m_labels; 115 116 u32 m_code_line = 0; 117 bool m_failed = false; 118 std::string m_last_error_str; 119 AssemblerError m_last_error = AssemblerError::OK; 120 121 using AliasMap = std::map<std::string, std::string>; 122 AliasMap m_aliases; 123 124 segment_t m_cur_segment = SEGMENT_CODE; 125 u32 m_segment_addr[SEGMENT_MAX] = {}; 126 int m_current_param = 0; 127 const AssemblerSettings m_settings; 128 }; 129 } // namespace DSP 130