From da1cb31ac2f3adf05c77ad57b8c23bff01fe415c Mon Sep 17 00:00:00 2001 From: Anthony Rabine Date: Thu, 16 Oct 2025 14:58:01 +0200 Subject: [PATCH] Using same objets between labels and instructions + fix load and store --- core/chip32/chip32_assembler.cpp | 241 +++++++++++++------------ core/chip32/chip32_assembler.h | 19 +- core/chip32/chip32_machine.h | 30 +-- core/chip32/chip32_vm.c | 9 +- core/story-manager/src/story_project.h | 9 +- core/tests/test_parser.cpp | 5 +- 6 files changed, 166 insertions(+), 147 deletions(-) diff --git a/core/chip32/chip32_assembler.cpp b/core/chip32/chip32_assembler.cpp index 263a7f4..4c64633 100644 --- a/core/chip32/chip32_assembler.cpp +++ b/core/chip32/chip32_assembler.cpp @@ -33,6 +33,7 @@ THE SOFTWARE. #include #include #include +#include namespace Chip32 { @@ -97,12 +98,12 @@ static inline void leu16_put(std::vector &container, uint16_t data } #define GET_REG(name, ra) if (!GetRegister(name, ra)) {\ - m_lastError.line -1; \ + m_lastError.line = -1; \ m_lastError.message = "ERROR! Bad register name: " + name; \ return false; } #define CHIP32_CHECK(instr, cond, error) if (!(cond)) { \ - m_lastError.line = instr.line; \ + m_lastError.line = instr->line; \ m_lastError.message = error; \ return false; } \ @@ -180,11 +181,11 @@ bool Assembler::GetRegisterName(uint8_t reg, std::string ®Name) return false; } -bool Assembler::CompileMnemonicArguments(Instr &instr) +bool Assembler::CompileMnemonicArguments(std::shared_ptr instr) { uint8_t ra, rb, rc; - switch(instr.code.opcode) + switch(instr->code.opcode) { case OP_NOP: case OP_HALT: @@ -192,17 +193,17 @@ bool Assembler::CompileMnemonicArguments(Instr &instr) // no arguments, just use the opcode break; case OP_SYSCALL: - instr.compiledArgs.push_back(static_cast(strtol(instr.args[0].c_str(), NULL, 0))); + instr->compiledArgs.push_back(static_cast(strtol(instr->args[0].c_str(), NULL, 0))); break; case OP_LCONS: - GET_REG(instr.args[0], ra); - instr.compiledArgs.push_back(ra); + GET_REG(instr->args[0], ra); + instr->compiledArgs.push_back(ra); // Detect address or immedate value - if ((instr.args[1].at(0) == '$') || (instr.args[1].at(0) == '.')) { - instr.useLabel = true; - leu32_put(instr.compiledArgs, 0); // reserve 4 bytes + if ((instr->args[1].at(0) == '$') || (instr->args[1].at(0) == '.')) { + instr->useLabel = true; + leu32_put(instr->compiledArgs, 0); // reserve 4 bytes } else { // immediate value - leu32_put(instr.compiledArgs, convertStringToLong(instr.args[1])); + leu32_put(instr->compiledArgs, convertStringToLong(instr->args[1])); } break; case OP_POP: @@ -211,8 +212,8 @@ bool Assembler::CompileMnemonicArguments(Instr &instr) case OP_SKIPNZ: case OP_CALL: case OP_JUMPR: - GET_REG(instr.args[0], ra); - instr.compiledArgs.push_back(ra); + GET_REG(instr->args[0], ra); + instr->compiledArgs.push_back(ra); break; case OP_MOV: case OP_ADD: @@ -226,38 +227,38 @@ bool Assembler::CompileMnemonicArguments(Instr &instr) case OP_OR: case OP_XOR: case OP_NOT: - GET_REG(instr.args[0], ra); - GET_REG(instr.args[1], rb); - instr.compiledArgs.push_back(ra); - instr.compiledArgs.push_back(rb); + GET_REG(instr->args[0], ra); + GET_REG(instr->args[1], rb); + instr->compiledArgs.push_back(ra); + instr->compiledArgs.push_back(rb); break; case OP_ADDI: case OP_SUBI: { - GET_REG(instr.args[0], ra); - instr.compiledArgs.push_back(ra); + GET_REG(instr->args[0], ra); + instr->compiledArgs.push_back(ra); - uint32_t op = convertStringToLong(instr.args[1]); + uint32_t op = convertStringToLong(instr->args[1]); if (op > 255) { return false; } - leu32_put(instr.compiledArgs, op); + leu32_put(instr->compiledArgs, op); break; } case OP_JUMP: // Reserve 2 bytes for address, it will be filled at the end - instr.useLabel = true; - instr.compiledArgs.push_back(0); - instr.compiledArgs.push_back(0); + instr->useLabel = true; + instr->compiledArgs.push_back(0); + instr->compiledArgs.push_back(0); break; case OP_STORE: // store @r4, r1, 2 - CHIP32_CHECK(instr, instr.args[0].at(0) == '@', "Missing @ sign before register") - instr.args[0].erase(0, 1); - GET_REG(instr.args[0], ra); - GET_REG(instr.args[1], rb); - instr.compiledArgs.push_back(ra); - instr.compiledArgs.push_back(rb); - instr.compiledArgs.push_back(static_cast(strtol(instr.args[2].c_str(), NULL, 0))); + CHIP32_CHECK(instr, instr->args[0].at(0) == '@', "Missing @ sign before register") + instr->args[0].erase(0, 1); + GET_REG(instr->args[0], ra); + GET_REG(instr->args[1], rb); + instr->compiledArgs.push_back(ra); + instr->compiledArgs.push_back(rb); + instr->compiledArgs.push_back(static_cast(strtol(instr->args[2].c_str(), NULL, 0))); break; case OP_LOAD: { @@ -265,26 +266,26 @@ bool Assembler::CompileMnemonicArguments(Instr &instr) // - load r0, @R1, 4 ; the address is located in a register // - load r0, $variable, 2 ; we use the variable address to get the value // - char prefix = instr.args[1].at(0); + char prefix = instr->args[1].at(0); // Register based if (prefix == '@') { - instr.args[1].erase(0, 1); // delete @ character - GET_REG(instr.args[0], ra); - GET_REG(instr.args[1], rb); - instr.compiledArgs.push_back(ra); - instr.compiledArgs.push_back(rb); - instr.compiledArgs.push_back(static_cast(strtol(instr.args[2].c_str(), NULL, 0))); + instr->args[1].erase(0, 1); // delete @ character + GET_REG(instr->args[0], ra); + GET_REG(instr->args[1], rb); + instr->compiledArgs.push_back(ra); + instr->compiledArgs.push_back(rb); + instr->compiledArgs.push_back(static_cast(strtol(instr->args[2].c_str(), NULL, 0))); } // Variable based else if (prefix == '$') { - instr.useLabel = true; - GET_REG(instr.args[0], ra); - instr.compiledArgs.push_back(ra | 0x80); // Flag this register with a bit to indicate an immediate address is following - leu32_put(instr.compiledArgs, 0); // reserve 4 bytes - instr.compiledArgs.push_back(static_cast(strtol(instr.args[2].c_str(), NULL, 0))); + instr->useLabel = true; + GET_REG(instr->args[0], ra); + instr->compiledArgs.push_back(ra | 0x80); // Flag this register with a bit to indicate an immediate address is following + leu32_put(instr->compiledArgs, 0); // reserve 4 bytes + instr->compiledArgs.push_back(static_cast(strtol(instr->args[2].c_str(), NULL, 0))); } else { @@ -296,23 +297,23 @@ bool Assembler::CompileMnemonicArguments(Instr &instr) case OP_CMP_EQ: case OP_CMP_GT: case OP_CMP_LT: - GET_REG(instr.args[0], ra); - GET_REG(instr.args[1], rb); - GET_REG(instr.args[2], rc); - instr.compiledArgs.push_back(ra); - instr.compiledArgs.push_back(rb); - instr.compiledArgs.push_back(rc); + GET_REG(instr->args[0], ra); + GET_REG(instr->args[1], rb); + GET_REG(instr->args[2], rc); + instr->compiledArgs.push_back(ra); + instr->compiledArgs.push_back(rb); + instr->compiledArgs.push_back(rc); break; default: - CHIP32_CHECK(instr, false, "Unsupported mnemonic: " + instr.mnemonic); + CHIP32_CHECK(instr, false, "Unsupported mnemonic: " + instr->mnemonic); break; } return true; } -bool Assembler::CompileConstantArgument(Instr &instr, const std::string &a) +bool Assembler::CompileConstantArgument(std::shared_ptr instr, const std::string &a) { - instr.compiledArgs.clear(); instr.args.clear(); instr.useLabel = false; + instr->compiledArgs.clear(); instr->args.clear(); instr->useLabel = false; // Check string if (a.size() > 2) @@ -322,19 +323,19 @@ bool Assembler::CompileConstantArgument(Instr &instr, const std::string &a) { for (unsigned int i = 1; i < (a.size() - 1); i++) { - instr.compiledArgs.push_back(a[i]); + instr->compiledArgs.push_back(a[i]); } - instr.compiledArgs.push_back(0); + instr->compiledArgs.push_back(0); return true; } // Detect label else if (a[0] == '.') { // Label must be 32-bit, throw an error if not the case - CHIP32_CHECK(instr, instr.dataTypeSize == 32, "Labels must be stored in a 32-bit area (DC32)") - instr.useLabel = true; - instr.args.push_back(a); - leu32_put(instr.compiledArgs, 0); // reserve 4 bytes + CHIP32_CHECK(instr, instr->dataTypeSize == 32, "Labels must be stored in a 32-bit area (DC32)") + instr->useLabel = true; + instr->args.push_back(a); + leu32_put(instr->compiledArgs, 0); // reserve 4 bytes return true; } } @@ -343,18 +344,18 @@ bool Assembler::CompileConstantArgument(Instr &instr, const std::string &a) uint32_t intVal = static_cast(strtol(a.c_str(), NULL, 0)); bool sizeOk = false; - if (((intVal <= UINT8_MAX) && (instr.dataTypeSize == 8)) || - ((intVal <= UINT16_MAX) && (instr.dataTypeSize == 16)) || - ((intVal <= UINT32_MAX) && (instr.dataTypeSize == 32))) { + if (((intVal <= UINT8_MAX) && (instr->dataTypeSize == 8)) || + ((intVal <= UINT16_MAX) && (instr->dataTypeSize == 16)) || + ((intVal <= UINT32_MAX) && (instr->dataTypeSize == 32))) { sizeOk = true; } CHIP32_CHECK(instr, sizeOk, "integer too high: " + std::to_string(intVal)); - if (instr.dataTypeSize == 8) { - instr.compiledArgs.push_back(intVal); - } else if (instr.dataTypeSize == 16) { - leu16_put(instr.compiledArgs, intVal); + if (instr->dataTypeSize == 8) { + instr->compiledArgs.push_back(intVal); + } else if (instr->dataTypeSize == 16) { + leu16_put(instr->compiledArgs, intVal); } else { - leu32_put(instr.compiledArgs, intVal); + leu32_put(instr->compiledArgs, intVal); } return true; } @@ -372,8 +373,8 @@ bool Assembler::Parse(const std::string &data) while(std::getline(data_stream, line)) { lineNum++; - Instr instr; - instr.line = lineNum; + auto instr = std::make_shared(); + instr->line = lineNum; size_t pos = line.find_first_of(";"); if (pos != std::string::npos) { line.erase(pos); @@ -398,9 +399,9 @@ bool Assembler::Parse(const std::string &data) CHIP32_CHECK(instr, (opcode[opcode.length() - 1] == ':') && (lineParts.size() == 1), "label must end with ':'"); // Label opcode.pop_back(); // remove the colon character - instr.mnemonic = opcode; - instr.isLabel = true; - instr.addr = code_addr; + instr->mnemonic = opcode; + instr->isLabel = true; + instr->addr = code_addr; CHIP32_CHECK(instr, m_labels.count(opcode) == 0, "duplicated label : " + opcode); m_labels[opcode] = instr; m_instructions.push_back(instr); @@ -409,20 +410,20 @@ bool Assembler::Parse(const std::string &data) // ======================================================================================= // INSTRUCTIONS // ======================================================================================= - else if (IsOpCode(opcode, instr.code)) + else if (IsOpCode(opcode, instr->code)) { - instr.mnemonic = opcode; + instr->mnemonic = opcode; bool nbArgsSuccess = false; // Test nedded arguments - if ((instr.code.nbAargs == 0) && (lineParts.size() == 1)) + if ((instr->code.nbAargs == 0) && (lineParts.size() == 1)) { nbArgsSuccess = true; // no arguments, solo mnemonic } - else if ((instr.code.nbAargs > 0) && (lineParts.size() >= 2)) + else if ((instr->code.nbAargs > 0) && (lineParts.size() >= 2)) { - instr.args.insert(instr.args.begin(), lineParts.begin() + 1, lineParts.end()); - CHIP32_CHECK(instr, instr.args.size() == instr.code.nbAargs, - "Bad number of parameters. Required: " + std::to_string(static_cast(instr.code.nbAargs)) + ", got: " + std::to_string(instr.args.size())); + instr->args.insert(instr->args.begin(), lineParts.begin() + 1, lineParts.end()); + CHIP32_CHECK(instr, instr->args.size() == instr->code.nbAargs, + "Bad number of parameters. Required: " + std::to_string(static_cast(instr->code.nbAargs)) + ", got: " + std::to_string(instr->args.size())); nbArgsSuccess = true; } else @@ -433,8 +434,8 @@ bool Assembler::Parse(const std::string &data) if (nbArgsSuccess) { CHIP32_CHECK(instr, CompileMnemonicArguments(instr) == true, "Compile failure, mnemonic or arguments"); - instr.addr = code_addr; - code_addr += 1 + instr.compiledArgs.size(); + instr->addr = code_addr; + code_addr += 1 + instr->compiledArgs.size(); m_instructions.push_back(instr); } } @@ -444,7 +445,7 @@ bool Assembler::Parse(const std::string &data) // ======================================================================================= else if (opcode[0] == '$') { - instr.mnemonic = opcode; + instr->mnemonic = opcode; CHIP32_CHECK(instr, (lineParts.size() >= 3), "bad number of parameters"); std::string type = lineParts[1]; @@ -456,51 +457,58 @@ bool Assembler::Parse(const std::string &data) // Parse data type size (8, 16, or 32) type.erase(0, 2); - instr.dataTypeSize = static_cast(strtol(type.c_str(), NULL, 0)); + instr->dataTypeSize = static_cast(strtol(type.c_str(), NULL, 0)); // Determine data type char typeChar = lineParts[1][1]; - instr.isRomData = (typeChar == 'C'); - instr.isRamData = (typeChar == 'V' || typeChar == 'Z'); - instr.isZeroData = (typeChar == 'Z'); + instr->isRomData = (typeChar == 'C'); + instr->isRamData = (typeChar == 'V' || typeChar == 'Z'); + instr->isZeroData = (typeChar == 'Z'); // ======================================================================================= // DC - ROM Constants (read-only data in program memory) // ======================================================================================= - if (instr.isRomData) + if (instr->isRomData) { - instr.addr = code_addr; + instr->addr = code_addr; m_labels[opcode] = instr; // location of the start of the data // Generate one instruction per argument // Reason: arguments may be labels, easier to replace later for (unsigned int i = 2; i < lineParts.size(); i++) { - CHIP32_CHECK(instr, CompileConstantArgument(instr, lineParts[i]), + // Create a new cloned instruction for each argument + auto clonedInstr = std::make_shared(*instr); + + CHIP32_CHECK(clonedInstr, CompileConstantArgument(clonedInstr, lineParts[i]), "Compile argument error, stopping."); - m_instructions.push_back(instr); - code_addr += instr.compiledArgs.size(); - instr.addr = code_addr; + m_instructions.push_back(clonedInstr); + code_addr += clonedInstr->compiledArgs.size(); + clonedInstr->addr = code_addr; } } // ======================================================================================= // DV - RAM Variables with initial values (data stored in ROM, copied to RAM at startup) // ======================================================================================= - else if (!instr.isZeroData) // DV + else if (!instr->isZeroData) // DV { // DV behaves like DC for data storage - instr.addr = dv_ram_addr; + instr->addr = dv_ram_addr; m_labels[opcode] = instr; // RAM address for this variable // Process all initial values (like DC) for (unsigned int i = 2; i < lineParts.size(); i++) { - CHIP32_CHECK(instr, CompileConstantArgument(instr, lineParts[i]), + // Create a new cloned instruction for each argument + auto clonedInstr = std::make_shared(*instr); + + CHIP32_CHECK(clonedInstr, CompileConstantArgument(clonedInstr, lineParts[i]), "Compile argument error, stopping."); - m_instructions.push_back(instr); - dv_ram_addr += instr.compiledArgs.size(); - instr.addr = dv_ram_addr; + m_instructions.push_back(clonedInstr); + dv_ram_addr += clonedInstr->compiledArgs.size(); + clonedInstr->addr = dv_ram_addr; + } } // ======================================================================================= @@ -512,20 +520,20 @@ bool Assembler::Parse(const std::string &data) CHIP32_CHECK(instr, lineParts.size() == 3, "DZ directive requires exactly one argument (number of elements)"); - instr.addr = dz_ram_addr; + instr->addr = dz_ram_addr; // Calculate size in bytes: num_elements * (type_size / 8) uint32_t numElements = static_cast(strtol(lineParts[2].c_str(), NULL, 0)); - instr.dataLen = static_cast(numElements * (instr.dataTypeSize / 8)); + instr->dataLen = static_cast(numElements * (instr->dataTypeSize / 8)); - dz_ram_addr += instr.dataLen; + dz_ram_addr += instr->dataLen; m_labels[opcode] = instr; m_instructions.push_back(instr); } } } - // Now that the RAM DV sier is known, compute DZ real data location after DV + // 2. Second pass: Now that the RAM DV size is known, compute DZ real data location after DV /* Position of Data in RAM @@ -536,39 +544,42 @@ Position of Data in RAM | DZ | ---------------------------- */ - - // 2. Second pass: replace all label or RAM data by the real address in memory for (auto &instr : m_instructions) { - if (instr.isZeroData) + if (instr->isZeroData) { - instr.addr += dv_ram_addr; + instr->addr += dv_ram_addr; } + } - if (instr.useLabel && (instr.args.size() > 0)) + + // 3. Third pass: replace all label or RAM data by the real address in memory + for (auto &instr : m_instructions) + { + if (instr->useLabel && (instr->args.size() > 0)) { // label is the first argument for jump, second position for LCONS and LOAD uint16_t argsIndex = 1; - if (instr.code.opcode == OP_JUMP) { + if (instr->code.opcode == OP_JUMP) { argsIndex = 0; } - std::string label = instr.args[argsIndex]; + std::string label = instr->args[argsIndex]; CHIP32_CHECK(instr, m_labels.count(label) > 0, "label not found: " + label); - uint32_t addr = m_labels[label].addr; + uint32_t addr = m_labels[label]->addr; std::cout << "LABEL: " << label << " , addr: " << addr << std::endl; - if (m_labels[label].isRamData) + if (m_labels[label]->isRamData) { addr |= CHIP32_RAM_OFFSET; } - instr.compiledArgs[argsIndex] = addr & 0xFF; - instr.compiledArgs[argsIndex+1] = (addr >> 8U) & 0xFF; - instr.compiledArgs[argsIndex+2] = (addr >> 16U) & 0xFF; - instr.compiledArgs[argsIndex+3] = (addr >> 24U) & 0xFF; + instr->compiledArgs[argsIndex] = addr & 0xFF; + instr->compiledArgs[argsIndex+1] = (addr >> 8U) & 0xFF; + instr->compiledArgs[argsIndex+2] = (addr >> 16U) & 0xFF; + instr->compiledArgs[argsIndex+3] = (addr >> 24U) & 0xFF; } } return true; } -} // namespace Chip32 +} // namespace Chip32 \ No newline at end of file diff --git a/core/chip32/chip32_assembler.h b/core/chip32/chip32_assembler.h index 3363a59..ac56a3b 100644 --- a/core/chip32/chip32_assembler.h +++ b/core/chip32/chip32_assembler.h @@ -31,6 +31,7 @@ THE SOFTWARE. #include #include #include +#include namespace Chip32 { @@ -92,8 +93,8 @@ public: static std::vector Split(const std::string &line); - std::vector::const_iterator begin() { return m_instructions.begin(); } - std::vector::const_iterator end() { return m_instructions.end(); } + std::vector>::const_iterator begin() { return m_instructions.begin(); } + std::vector>::const_iterator end() { return m_instructions.end(); } // Returns the register number from the name bool GetRegister(const std::string ®Name, uint8_t ®); @@ -101,7 +102,7 @@ public: Error GetLastError() { return m_lastError; } - bool GetMain(Instr &instr) const { + bool GetMain(std::shared_ptr &instr) const { // Find the main label bool success = m_labels.count(".main") == 1; @@ -115,17 +116,17 @@ public: } private: - bool CompileMnemonicArguments(Instr &instr); + bool CompileMnemonicArguments(std::shared_ptr instr); - // label, address - std::map m_labels; + // label, shared pointer to instruction + std::map> m_labels; Error m_lastError; - std::vector m_instructions; - bool CompileConstantArgument(Instr &instr, const std::string &a); + std::vector> m_instructions; + bool CompileConstantArgument(std::shared_ptr instr, const std::string &a); }; } -#endif // CHIP32_ASSEMBLER_H +#endif // CHIP32_ASSEMBLER_H \ No newline at end of file diff --git a/core/chip32/chip32_machine.h b/core/chip32/chip32_machine.h index 2b0a503..2e7fdca 100644 --- a/core/chip32/chip32_machine.h +++ b/core/chip32/chip32_machine.h @@ -58,10 +58,10 @@ public: chip32_binary_header_init(&header); - Chip32::Instr instr; - if (assembler.GetMain(instr)) + std::shared_ptr mainInstr; + if (assembler.GetMain(mainInstr)) { - header.entry_point = instr.addr; + header.entry_point = mainInstr->addr; } // else: no main found, we try to start at address zero... @@ -70,37 +70,37 @@ public: // ==================================================================== // CODE INSTRUCTIONS // ==================================================================== - if (instr.isRomCode()) + if (instr->isRomCode()) { // Ajouter l'opcode - codeSection.push_back(instr.code.opcode); + codeSection.push_back(instr->code.opcode); // Ajouter les arguments compilés - std::copy(instr.compiledArgs.begin(), - instr.compiledArgs.end(), + std::copy(instr->compiledArgs.begin(), + instr->compiledArgs.end(), std::back_inserter(codeSection)); } // ==================================================================== // ROM DATA - Distinguer DC (vraies constantes) de DV init data // ==================================================================== - else if (instr.isRomData && !instr.isRamData) + else if (instr->isRomData && !instr->isRamData) { - std::copy(instr.compiledArgs.begin(), - instr.compiledArgs.end(), + std::copy(instr->compiledArgs.begin(), + instr->compiledArgs.end(), std::back_inserter(constSection)); } // ==================================================================== // RAM VARIABLES // ==================================================================== - else if (instr.isRamData) + else if (instr->isRamData) { // ==================================================================== // ZEROED DATA (DZ) // ==================================================================== - if (instr.isZeroData) + if (instr->isZeroData) { - header.bss_size += instr.dataLen; + header.bss_size += instr->dataLen; } // ==================================================================== // INITIALIZED RAM VARIABLES (DV) @@ -109,8 +109,8 @@ public: { // Ces données appartiennent à cette variable DV initDataSection.insert(initDataSection.end(), - instr.compiledArgs.begin(), - instr.compiledArgs.end()); + instr->compiledArgs.begin(), + instr->compiledArgs.end()); } } } diff --git a/core/chip32/chip32_vm.c b/core/chip32/chip32_vm.c index f9ea032..61d0a02 100644 --- a/core/chip32/chip32_vm.c +++ b/core/chip32/chip32_vm.c @@ -241,20 +241,21 @@ chip32_result_t chip32_step(chip32_ctx_t *ctx) uint32_t addr = 0; uint8_t size = 0; - // Variable based + // Variable based, validity of reg will be verified after if (reg1 & 0x80) { reg1 &= 0x7F; + _CHECK_REGISTER_VALID(reg1); addr = _NEXT_INT(ctx); size = _NEXT_BYTE; } // address is located in reg2 reg else { + _CHECK_REGISTER_VALID(reg1); const uint8_t reg2 = _NEXT_BYTE; - const uint8_t size = _NEXT_BYTE; - _CHECK_REGISTER_VALID(reg1) - _CHECK_REGISTER_VALID(reg2) + _CHECK_REGISTER_VALID(reg2); + size = _NEXT_BYTE; addr = ctx->registers[reg2]; } diff --git a/core/story-manager/src/story_project.h b/core/story-manager/src/story_project.h index 3161740..c24a09d 100644 --- a/core/story-manager/src/story_project.h +++ b/core/story-manager/src/story_project.h @@ -40,7 +40,14 @@ public: } bool FindMain(Chip32::Instr &mainLine) { - return m_assembler.GetMain(mainLine); + + std::shared_ptr m; + bool success = m_assembler.GetMain(m); + if (success) + { + mainLine = *m; + } + return success; } bool GenerateCompleteProgram(std::string &assembly); diff --git a/core/tests/test_parser.cpp b/core/tests/test_parser.cpp index 715c3ac..46b6df9 100644 --- a/core/tests/test_parser.cpp +++ b/core/tests/test_parser.cpp @@ -300,9 +300,8 @@ TEST_CASE("Binary format validation") REQUIRE(header.const_size > 0); // Has ROM constants REQUIRE(header.bss_size > 0); // Has RAM REQUIRE(header.code_size > 0); // Has code - REQUIRE(header.data_size == header.bss_size); // Must match - - + REQUIRE(header.bss_size == 144); + REQUIRE(header.data_size == 7); chip32_binary_build_stats(&header, &stats);