@@ -16,6 +16,7 @@ Assembler::Assembler() {
1616void Assembler::assemble (std::string code, RAM* mem) {
1717 Logger::loggerInst->info (" Assembly process started..." );
1818 std::vector<std::string> lines = splitString (code,' \n ' );
19+ std::map<sint,sint> datablock;
1920 varbel_names.clear ();
2021 subroutines.clear ();
2122
@@ -78,6 +79,7 @@ void Assembler::assemble(std::string code, RAM* mem) {
7879 int state = 0 ; // where in the code are we? 0 = main code, 1 = subroutine
7980 subroutine* curr_s = nullptr ; // stores the current subroutine information
8081 std::string curr_s_name = " " ;
82+ bool curr_s_ret = false ;
8183 int globalvarcount = 0 ; // how many global vars have been defined so far
8284 // how many local vars have been defined so far (in case of state == 1)
8385 // start value of 2 is necessary because 0=return-address, 1=previous frame pointer and 2=previous stack pointer
@@ -94,6 +96,13 @@ void Assembler::assemble(std::string code, RAM* mem) {
9496 if (state == 0 ) {
9597 if (words.size () > 1 && checkIdentifier (words.at (1 ))) {
9698 varbel_names.insert (std::make_pair (words.at (1 ),globalvarcount));
99+ if (words.size () > 2 ) {
100+ for (int i = 2 ; i < words.size (); ++i) {
101+ datablock.insert (std::make_pair (globalvarcount,isNumeric (words.at (i))));
102+ ++globalvarcount;
103+ }
104+ --globalvarcount;
105+ }
97106 ++globalvarcount; // global vars are zero basedly indexed since the data pointer points to the first available ram slot
98107 } else if (words.size () == 1 ) {
99108 Logger::loggerInst->error (" Missing identifier after keyword 'define' on line " , i + 1 );
@@ -122,6 +131,7 @@ void Assembler::assemble(std::string code, RAM* mem) {
122131 }
123132 } else if (words.at (0 ) == " endfunction" ) {
124133 // reset everything to state 0
134+ if (!curr_s_ret) Logger::loggerInst->warning (" Function '" + curr_s_name + " ' has no return statement! This will most likely cause dangling pointers!" );
125135 localvarcount = 2 ;
126136 curr_s = nullptr ;
127137 curr_s_name = " " ;
@@ -131,6 +141,7 @@ void Assembler::assemble(std::string code, RAM* mem) {
131141 state = 1 ;
132142 curr_s = &subroutines.at (words.at (1 ));
133143 curr_s_name = words.at (1 );
144+ curr_s_ret = false ;
134145 } else if (words.at (0 ) == " entrypoint" ) {
135146 // set the entrypoint address
136147 mem->setValueAt (0 ,address + 1 );
@@ -176,6 +187,7 @@ void Assembler::assemble(std::string code, RAM* mem) {
176187 return ;
177188 }
178189 } else if (words.size () == 1 ) {
190+ if (words.at (0 ) == " ret" ) curr_s_ret = true ;
179191 // if mnemonic has no arguments, store the apropriate op-code and a null argument
180192 if (Constants::OP_CODES.find (words.at (0 )) != Constants::OP_CODES.end ()) {
181193 mem->setValueAt (address + 1 , Constants::OP_CODES.at (words.at (0 )));
@@ -193,6 +205,7 @@ void Assembler::assemble(std::string code, RAM* mem) {
193205 if (adcp.valid ) {
194206 mem->setValueAt (address + 1 , Constants::OP_CODES.at (words.at (0 )) + adcp.op_add );
195207 mem->setValueAt (address + 2 , adcp.address );
208+ if (words.at (0 ) == " ldi" && adcp.op_add == Constants::ADR_REG) Logger::loggerInst->warning (" Using register-address as argument for indirect load 'LDI', which most likely won't have the expected result, on line " , i + 1 );
196209 } else {
197210 Logger::loggerInst->info (" Assembly process aborted!" );
198211 emit assemblyDone ();
@@ -219,6 +232,23 @@ void Assembler::assemble(std::string code, RAM* mem) {
219232 emit assemblyDone ();
220233 return ;
221234 }
235+ } else if (words.at (0 ) == " ld" || words.at (0 ) == " ldi" ) {
236+ addressCompound adcp = getAddress (words.at (1 ), state, curr_s_name);
237+ addressCompound target_reg = getAddress (words.at (2 ),state,curr_s_name);
238+ if (adcp.valid && target_reg.valid && target_reg.op_add == Constants::ADR_REG) {
239+ sint reg_number = 0 ;
240+ while (target_reg.address > 0 ) {
241+ ++reg_number;
242+ target_reg.address >>= 1 ;
243+ }
244+ mem->setValueAt (address + 1 , Constants::OP_CODES.at (words.at (0 )) + adcp.op_add + (reg_number << 24 ));
245+ mem->setValueAt (address + 2 , adcp.address );
246+ if (words.at (0 ) == " ldi" && adcp.op_add == Constants::ADR_REG) Logger::loggerInst->warning (" Using register-address as argument for indirect load 'LDI', which most likely won't have the expected result, on line " , i + 1 );
247+ } else {
248+ Logger::loggerInst->info (" Assembly process aborted!" );
249+ emit assemblyDone ();
250+ return ;
251+ }
222252 } else {
223253 Logger::loggerInst->error (" Too many arguments for mnemonic '" + words.at (0 ) + " ' on line " , i + 1 );
224254 Logger::loggerInst->info (" Assembly process aborted!" );
@@ -242,6 +272,9 @@ void Assembler::assemble(std::string code, RAM* mem) {
242272 && Constants::OP_CODES.find (words.at (0 )) != Constants::OP_CODES.end ()) address += 2 ; // normal op code requires two memory slots (OP-Code + Argument)
243273 }
244274 mem->setValueAt (1 ,address + 1 ); // set the value the datapointer should be set to
275+ for (std::pair<sint,sint> datavalue : datablock) {
276+ mem->setValueAt (address + 1 + datavalue.first ,datavalue.second );
277+ }
245278 Logger::loggerInst->info (" Assembly process done!" );
246279 emit assemblyDone ();
247280}
@@ -275,11 +308,13 @@ void Assembler::verify(std::string code) {
275308 if (w == " function" ) isFunctionDef = true ; // curent line is a function def
276309 else if (isFunctionDef) {
277310 if (i == 1 ) { // first word after "function" is equal to the name of the subroutine
278- if (checkIdentifier (w)) name = w;
311+ checkIdentifier (w);
312+ name = w;
279313 paramcount = 0 ;
280314 } else if (i > 1 ) {
281315 ++paramcount;
282- if (checkIdentifier (w)) s.param_names .insert (std::make_pair (w,paramcount)); // map param_name to position of parameter
316+ checkIdentifier (w);
317+ s.param_names .insert (std::make_pair (w,paramcount)); // map param_name to position of parameter
283318 }
284319 } else if (w.at (0 ) == ' :' ) {
285320 varbel_names.insert (std::make_pair (w.substr (1 ),address + 2 ));
@@ -296,6 +331,7 @@ void Assembler::verify(std::string code) {
296331 int state = 0 ; // where in the code are we? 0 = main code, 1 = subroutine
297332 subroutine* curr_s = nullptr ; // stores the current subroutine information
298333 std::string curr_s_name = " " ;
334+ bool curr_s_ret = false ;
299335 int globalvarcount = 0 ; // how many global vars have been defined so far
300336 // how many local vars have been defined so far (in case of state == 1)
301337 // start value of 2 is necessary because 0=return-address, 1=previous frame pointer and 2=previous stack pointer
@@ -324,15 +360,22 @@ void Assembler::verify(std::string code) {
324360 }
325361 } else if (words.at (0 ) == " endfunction" ) {
326362 // reset everything to state 0
363+ if (!curr_s_ret) Logger::loggerInst->warning (" Function '" + curr_s_name + " ' has no return statement! This will most likely cause dangling pointers!" );
327364 localvarcount = 2 ;
328365 curr_s = nullptr ;
329366 curr_s_name = " " ;
330367 state = 0 ;
331368 } else if (words.at (0 ) == " function" ) {
332369 // init everything necessary for state 1
333- state = 1 ;
334- curr_s = &subroutines.at (words.at (1 ));
335- curr_s_name = words.at (1 );
370+ if (words.size () > 1 ) {
371+ if (state == 1 ) Logger::loggerInst->error (" Function '" + curr_s_name + " '' is missing terminator ('endfunction')" );
372+ state = 1 ;
373+ curr_s_ret = false ;
374+ curr_s = &subroutines.at (words.at (1 ));
375+ curr_s_name = words.at (1 );
376+ } else {
377+ Logger::loggerInst->error (" Function definition is missing identifier on line " , i + 1 );
378+ }
336379 } else if (words.at (0 ) == " entrypoint" ) {
337380 } else {
338381 if (words.at (0 ).at (0 ) == ' #' || words.at (0 ).at (0 ) == ' :' ) {
@@ -357,6 +400,7 @@ void Assembler::verify(std::string code) {
357400 Logger::loggerInst->error (" Missing function-identifier after mnemonic 'call' on line " , i + 1 );
358401 }
359402 } else if (words.size () == 1 ) {
403+ if (words.at (0 ) == " ret" ) curr_s_ret = true ;
360404 // if mnemonic has no arguments, store the apropriate op-code and a null argument
361405 if (Constants::OP_CODES.find (words.at (0 )) == Constants::OP_CODES.end ()) {
362406 Logger::loggerInst->error (" Unrecognized mnemonic on line " , i + 1 );
@@ -392,6 +436,7 @@ void Assembler::verify(std::string code) {
392436 && Constants::ASSEMBLY_INST.find (words.at (0 )) == Constants::ASSEMBLY_INST.end ()
393437 && Constants::OP_CODES.find (words.at (0 )) != Constants::OP_CODES.end ()) address += 2 ; // normal op code requires two memory slots (OP-Code + Argument)
394438 }
439+ if (state == 1 ) Logger::loggerInst->error (" Function '" + curr_s_name + " '' is missing terminator ('endfunction')" );
395440 Logger::loggerInst->info (" Code verification done! If no error messages showed up, your code(-syntax) should be fine." );
396441}
397442
@@ -437,8 +482,16 @@ Assembler::addressCompound Assembler::getAddress(std::string idf, int state, std
437482 if (std::regex_match (idf,std::regex (" ^-?[0-9]+" )) || std::regex_match (idf,std::regex (" ^-?0x[a-f0-9]+" ))) {
438483 // if identifier is a number, it serves as the effective address/value
439484 Logger::loggerInst->debug (" Identifier is numeric, absolute" );
440- sint effective_address = std::stoi (idf,0 ,0 );
441- result.address = effective_address;
485+ try {
486+ sint effective_address = std::stoi (idf,0 ,0 );
487+ result.address = effective_address;
488+ } catch (const std::out_of_range& e) {
489+ Logger::loggerInst->debug (e.what ());
490+ Logger::loggerInst->error (" Number is too big to fit in a 32-Bit Integer. " + idf);
491+ result.address = 0 ;
492+ return result;
493+ }
494+
442495 result.op_add = isValue ? Constants::ADR_ABSOLUTE : Constants::VAL_ABSOLUTE;
443496 result.valid = true ;
444497 } else if (idf.find (' [' ) != std::string::npos) {
@@ -505,8 +558,14 @@ Assembler::addressCompound Assembler::getAddress(std::string idf, int state, std
505558
506559sint Assembler::isNumeric (std::string idf) {
507560 if (std::regex_match (idf,std::regex (" ^-?[0-9]+" )) || std::regex_match (idf,std::regex (" ^-?0x[a-f0-9]+" ))) {
508- sint effective_address = std::stoi (idf,0 ,0 );;
509- return effective_address;
561+ try {
562+ sint effective_address = std::stoi (idf,0 ,0 );
563+ return effective_address;
564+ } catch (const std::out_of_range& e) {
565+ Logger::loggerInst->debug (e.what ());
566+ Logger::loggerInst->error (" Number is too big to fit in a 32-Bit Integer. " + idf);
567+ return -1 ;
568+ }
510569 }
511570 return -1 ;
512571}
0 commit comments