mirror of
				https://github.com/simon987/Much-Assembly-Required.git
				synced 2025-10-31 00:16:51 +00:00 
			
		
		
		
	Refactoring & code style (#212)
This commit is contained in:
		
							parent
							
								
									634af8859f
								
							
						
					
					
						commit
						03ff2e5527
					
				| @ -170,7 +170,7 @@ public class Assembler { | ||||
|                         } catch (IllegalArgumentException e) { | ||||
|                             throw new InvalidOperandException( | ||||
|                                     "Invalid string operand \"" + string + "\": " + e.getMessage(), | ||||
|                                 currentLine); | ||||
|                                     currentLine); | ||||
|                         } | ||||
| 
 | ||||
|                         out.write(string.getBytes(StandardCharsets.UTF_16BE)); | ||||
| @ -318,7 +318,7 @@ public class Assembler { | ||||
|         /*  the EQU pseudo instruction is equivalent to the #define compiler directive in C/C++ | ||||
|          *  usage: constant_name EQU <immediate_value> | ||||
|          *  A constant treated the same way as a label. | ||||
|         */ | ||||
|          */ | ||||
|         line = line.trim(); | ||||
|         String[] tokens = line.split("\\s+"); | ||||
| 
 | ||||
| @ -362,7 +362,47 @@ public class Assembler { | ||||
|         ByteArrayOutputStream out = new ByteArrayOutputStream(); | ||||
| 
 | ||||
|         //Pass 1: Get code origin | ||||
|         for (currentLine = 0; currentLine < lines.length; currentLine++) { | ||||
|         getCodeOrigin(lines, result); | ||||
|         //Pass 2: Save label names and location | ||||
|         saveLabelNamesAndLocation(lines, result); | ||||
|         //Pass 3: encode instructions | ||||
|         encodeInstructions(lines, result, out); | ||||
| 
 | ||||
| 
 | ||||
|         //If the code contains OffsetOverFlowException(s), don't bother writing the assembled bytes to memory | ||||
|         boolean writeToMemory = true; | ||||
|         for (Exception e : result.exceptions) { | ||||
|             if (e instanceof OffsetOverflowException) { | ||||
|                 writeToMemory = false; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (writeToMemory) { | ||||
|             result.bytes = out.toByteArray(); | ||||
|         } else { | ||||
|             result.bytes = new byte[0]; | ||||
|             LogManager.LOGGER.fine("Skipping writing assembled bytes to memory. (OffsetOverflowException)"); | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
|             out.close(); | ||||
|         } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
| 
 | ||||
|         LogManager.LOGGER.info("Assembled " + result.bytes.length + " bytes (" + result.exceptions.size() + " errors)"); | ||||
|         for (AssemblyException e : result.exceptions) { | ||||
|             LogManager.LOGGER.severe(e.getMessage() + '@' + e.getLine()); | ||||
|         } | ||||
|         LogManager.LOGGER.info('\n' + Util.toHex(result.bytes)); | ||||
| 
 | ||||
|         return result; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private void getCodeOrigin(String[] lines, AssemblyResult result) { | ||||
|         for (int currentLine = 0; currentLine < lines.length; currentLine++) { | ||||
|             try { | ||||
|                 checkForORGInstruction(lines[currentLine], result, currentLine); | ||||
| 
 | ||||
| @ -373,10 +413,11 @@ public class Assembler { | ||||
|                 //Ignore error | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|         //Pass 2: Save label names and location | ||||
|     private void saveLabelNamesAndLocation(String[] lines, AssemblyResult result) { | ||||
|         int currentOffset = 0; | ||||
|         for (currentLine = 0; currentLine < lines.length; currentLine++) { | ||||
|         for (int currentLine = 0; currentLine < lines.length; currentLine++) { | ||||
|             try { | ||||
|                 checkForLabel(lines[currentLine], result, (char)currentOffset); | ||||
| 
 | ||||
| @ -394,11 +435,11 @@ public class Assembler { | ||||
| 
 | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|         //Pass 3: encode instructions | ||||
|         currentOffset = 0; | ||||
|         for (currentLine = 0; currentLine < lines.length; currentLine++) { | ||||
|     private void encodeInstructions(String[] lines, AssemblyResult result, ByteArrayOutputStream out) { | ||||
|         int currentOffset = 0; | ||||
|         for (int currentLine = 0; currentLine < lines.length; currentLine++) { | ||||
| 
 | ||||
|             String line = lines[currentLine]; | ||||
| 
 | ||||
| @ -439,36 +480,6 @@ public class Assembler { | ||||
|                 ioE.printStackTrace(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         //If the code contains OffsetOverFlowException(s), don't bother writing the assembled bytes to memory | ||||
|         boolean writeToMemory = true; | ||||
|         for (Exception e : result.exceptions) { | ||||
|             if (e instanceof OffsetOverflowException) { | ||||
|                 writeToMemory = false; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (writeToMemory) { | ||||
|             result.bytes = out.toByteArray(); | ||||
|         } else { | ||||
|             result.bytes = new byte[0]; | ||||
|             LogManager.LOGGER.fine("Skipping writing assembled bytes to memory. (OffsetOverflowException)"); | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
|             out.close(); | ||||
|         } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
| 
 | ||||
|         LogManager.LOGGER.info("Assembled " + result.bytes.length + " bytes (" + result.exceptions.size() + " errors)"); | ||||
|         for (AssemblyException e : result.exceptions) { | ||||
|             LogManager.LOGGER.severe(e.getMessage() + '@' + e.getLine()); | ||||
|         } | ||||
|         LogManager.LOGGER.info('\n' + Util.toHex(result.bytes)); | ||||
| 
 | ||||
|         return result; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -207,104 +207,11 @@ public class CPU implements MongoSerializable { | ||||
|             ip++; | ||||
|             instruction.execute(status); | ||||
|         } else if (source == Operand.IMMEDIATE_VALUE) { | ||||
|             ip++; | ||||
|             int sourceValue = memory.get(ip); | ||||
| 
 | ||||
|             if (destination == 0) { | ||||
|                 //Single operand | ||||
|                 ip++; | ||||
|                 instruction.execute(sourceValue, status); | ||||
|             } else if (destination == Operand.IMMEDIATE_VALUE) { | ||||
|                 //Destination is an immediate value too | ||||
|                 //this shouldn't happen | ||||
|                 LogManager.LOGGER.severe("Trying to execute an instruction with 2" + | ||||
|                         "immediate values as operands"); //todo remove debug info | ||||
| 
 | ||||
|             } else if (destination == Operand.IMMEDIATE_VALUE_MEM) { | ||||
|                 //Destination is memory immediate | ||||
|                 ip += 2; | ||||
|                 instruction.execute(memory, memory.get(ip - 1), sourceValue, status); | ||||
|             } else if (destination <= registerSetSize) { | ||||
|                 //Destination is a register | ||||
|                 ip++; | ||||
|                 instruction.execute(registerSet, destination, sourceValue, status); | ||||
| 
 | ||||
|             } else if (destination <= registerSetSize * 2) { | ||||
|                 //Destination is [reg] | ||||
|                 ip++; | ||||
|                 instruction.execute(memory, registerSet.get(destination - registerSetSize), sourceValue, status); | ||||
|             } else { | ||||
|                 //Assuming that destination is [reg + x] | ||||
|                 ip += 2; | ||||
|                 instruction.execute(memory, registerSet.get(destination - registerSetSize - registerSetSize) + memory.get(ip - 1), | ||||
|                         sourceValue, status); | ||||
|             } | ||||
| 
 | ||||
|             executeImmediateValue(instruction, source, destination); | ||||
|         } else if (source == Operand.IMMEDIATE_VALUE_MEM) { | ||||
|             //Source is [x] | ||||
|             ip++; | ||||
|             int sourceValue = memory.get(memory.get(ip)); | ||||
| 
 | ||||
|             if (destination == 0) { | ||||
|                 //Single operand | ||||
|                 ip++; | ||||
|                 instruction.execute(memory, memory.get(ip - 1), status); | ||||
|             } else if (destination == Operand.IMMEDIATE_VALUE) { | ||||
|                 //Destination is an immediate value | ||||
| 
 | ||||
|                 //this shouldn't happen | ||||
|                 LogManager.LOGGER.severe("Trying to execute an instruction with an" + | ||||
|                         "immediate values as dst operand"); //todo remove debug info | ||||
|             } else if (destination == Operand.IMMEDIATE_VALUE_MEM) { | ||||
|                 //Destination is memory immediate too | ||||
|                 ip += 2; | ||||
|                 instruction.execute(memory, memory.get(ip - 1), sourceValue, status); | ||||
|             } else if (destination <= registerSetSize) { | ||||
|                 //Destination is a register | ||||
|                 ip++; | ||||
|                 instruction.execute(registerSet, destination, sourceValue, status); | ||||
|             } else if (destination <= registerSetSize * 2) { | ||||
|                 //Destination is [reg] | ||||
|                 ip++; | ||||
|                 instruction.execute(memory, registerSet.get(destination - registerSetSize), sourceValue, status); | ||||
|             } else { | ||||
|                 //Assuming that destination is [reg + x] | ||||
|                 ip += 2; | ||||
|                 instruction.execute(memory, registerSet.get(destination - registerSetSize - registerSetSize) + memory.get(ip - 1), sourceValue, status); | ||||
|             } | ||||
| 
 | ||||
|             executeImmediateValueMem(instruction, source, destination); | ||||
|         } else if (source <= registerSetSize) { | ||||
|             //Source is a register | ||||
| 
 | ||||
|             if (destination == 0) { | ||||
|                 //Single operand | ||||
|                 ip++; | ||||
|                 instruction.execute(registerSet, source, status); | ||||
| 
 | ||||
|             } else if (destination == Operand.IMMEDIATE_VALUE) { | ||||
|                 //Destination is an immediate value | ||||
|                 //this shouldn't happen | ||||
|                 LogManager.LOGGER.severe("Trying to execute an instruction with an" + | ||||
|                         "immediate values as dst operand"); //todo remove debug info | ||||
|             } else if (destination == Operand.IMMEDIATE_VALUE_MEM) { | ||||
|                 //Destination is memory immediate | ||||
|                 ip += 2; | ||||
|                 instruction.execute(memory, memory.get(ip - 1), registerSet, source, status); | ||||
|             } else if (destination <= registerSetSize) { | ||||
|                 //Destination is a register too | ||||
|                 ip++; | ||||
|                 instruction.execute(registerSet, destination, registerSet, source, status); | ||||
|             } else if (destination <= registerSetSize * 2) { | ||||
|                 //Destination is [reg] | ||||
|                 ip++; | ||||
|                 instruction.execute(memory, registerSet.get(destination - registerSetSize), registerSet, source, status); | ||||
|             } else { | ||||
|                 //Assuming that destination is [reg + x] | ||||
|                 ip += 2; | ||||
|                 instruction.execute(memory, registerSet.get(destination - registerSetSize - registerSetSize) + memory.get(ip - 1), | ||||
|                         registerSet, source, status); | ||||
|             } | ||||
| 
 | ||||
|             executeSourceIsRegister(instruction, source, destination); | ||||
|         } else if (source <= registerSetSize * 2) { | ||||
|             //Source is [reg] | ||||
|             if (destination == 0) { | ||||
| @ -374,6 +281,107 @@ public class CPU implements MongoSerializable { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void executeSourceIsRegister(Instruction instruction, int source, int destination) { | ||||
|         //Source is a register | ||||
|         if (destination == 0) { | ||||
|             //Single operand | ||||
|             ip++; | ||||
|             instruction.execute(registerSet, source, status); | ||||
| 
 | ||||
|         } else if (destination == Operand.IMMEDIATE_VALUE) { | ||||
|             //Destination is an immediate value | ||||
|             //this shouldn't happen | ||||
|             LogManager.LOGGER.severe("Trying to execute an instruction with an" + | ||||
|                     "immediate values as dst operand"); //todo remove debug info | ||||
|         } else if (destination == Operand.IMMEDIATE_VALUE_MEM) { | ||||
|             //Destination is memory immediate | ||||
|             ip += 2; | ||||
|             instruction.execute(memory, memory.get(ip - 1), registerSet, source, status); | ||||
|         } else if (destination <= registerSetSize) { | ||||
|             //Destination is a register too | ||||
|             ip++; | ||||
|             instruction.execute(registerSet, destination, registerSet, source, status); | ||||
|         } else if (destination <= registerSetSize * 2) { | ||||
|             //Destination is [reg] | ||||
|             ip++; | ||||
|             instruction.execute(memory, registerSet.get(destination - registerSetSize), registerSet, source, status); | ||||
|         } else { | ||||
|             //Assuming that destination is [reg + x] | ||||
|             ip += 2; | ||||
|             instruction.execute(memory, registerSet.get(destination - registerSetSize - registerSetSize) + memory.get(ip - 1), | ||||
|                     registerSet, source, status); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void executeImmediateValue(Instruction instruction, int source, int destination) { | ||||
|         ip++; | ||||
|         int sourceValue = memory.get(ip); | ||||
| 
 | ||||
|         if (destination == 0) { | ||||
|             //Single operand | ||||
|             ip++; | ||||
|             instruction.execute(sourceValue, status); | ||||
|         } else if (destination == Operand.IMMEDIATE_VALUE) { | ||||
|             //Destination is an immediate value too | ||||
|             //this shouldn't happen | ||||
|             LogManager.LOGGER.severe("Trying to execute an instruction with 2" + | ||||
|                     "immediate values as operands"); //todo remove debug info | ||||
| 
 | ||||
|         } else if (destination == Operand.IMMEDIATE_VALUE_MEM) { | ||||
|             //Destination is memory immediate | ||||
|             ip += 2; | ||||
|             instruction.execute(memory, memory.get(ip - 1), sourceValue, status); | ||||
|         } else if (destination <= registerSetSize) { | ||||
|             //Destination is a register | ||||
|             ip++; | ||||
|             instruction.execute(registerSet, destination, sourceValue, status); | ||||
| 
 | ||||
|         } else if (destination <= registerSetSize * 2) { | ||||
|             //Destination is [reg] | ||||
|             ip++; | ||||
|             instruction.execute(memory, registerSet.get(destination - registerSetSize), sourceValue, status); | ||||
|         } else { | ||||
|             //Assuming that destination is [reg + x] | ||||
|             ip += 2; | ||||
|             instruction.execute(memory, registerSet.get(destination - registerSetSize - registerSetSize) + memory.get(ip - 1), | ||||
|                     sourceValue, status); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void executeImmediateValueMem(Instruction instruction, int source, int destination) { | ||||
|         //Source is [x] | ||||
|         ip++; | ||||
|         int sourceValue = memory.get(memory.get(ip)); | ||||
| 
 | ||||
|         if (destination == 0) { | ||||
|             //Single operand | ||||
|             ip++; | ||||
|             instruction.execute(memory, memory.get(ip - 1), status); | ||||
|         } else if (destination == Operand.IMMEDIATE_VALUE) { | ||||
|             //Destination is an immediate value | ||||
| 
 | ||||
|             //this shouldn't happen | ||||
|             LogManager.LOGGER.severe("Trying to execute an instruction with an" + | ||||
|                     "immediate values as dst operand"); //todo remove debug info | ||||
|         } else if (destination == Operand.IMMEDIATE_VALUE_MEM) { | ||||
|             //Destination is memory immediate too | ||||
|             ip += 2; | ||||
|             instruction.execute(memory, memory.get(ip - 1), sourceValue, status); | ||||
|         } else if (destination <= registerSetSize) { | ||||
|             //Destination is a register | ||||
|             ip++; | ||||
|             instruction.execute(registerSet, destination, sourceValue, status); | ||||
|         } else if (destination <= registerSetSize * 2) { | ||||
|             //Destination is [reg] | ||||
|             ip++; | ||||
|             instruction.execute(memory, registerSet.get(destination - registerSetSize), sourceValue, status); | ||||
|         } else { | ||||
|             //Assuming that destination is [reg + x] | ||||
|             ip += 2; | ||||
|             instruction.execute(memory, registerSet.get(destination - registerSetSize - registerSetSize) + memory.get(ip - 1), sourceValue, status); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public Document mongoSerialise() { | ||||
|         Document dbObject = new Document(); | ||||
|  | ||||
| @ -127,32 +127,27 @@ public class OperandTest { | ||||
|         } | ||||
| 
 | ||||
|         //Invalid operands | ||||
|         try{ new Operand("aa", labels, registerSet, 0); } catch (InvalidOperandException e){ | ||||
|                 //It's not a valid Operand; that's okey, just continue; VALID FOR ALL THE OTHER CATCH SENTENCES | ||||
|         try{ new Operand("aa", labels, registerSet, 0); } catch (InvalidOperandException ignored){ | ||||
|             //It's not a valid Operand; that's okay, just continue; VALID FOR ALL THE OTHER CATCH SENTENCES | ||||
|         } | ||||
|         try{   new Operand("a1", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{   new Operand("a_", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{   new Operand("_a", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{   new Operand("_1", labels, registerSet, 0); } catch (InvalidOperandException e){        } | ||||
|         try{    new Operand("S", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{   new Operand("label1_", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{   new Operand("+label1", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{    new Operand("[- 12]", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{    new Operand("[12+1]", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{    new Operand("[+label1", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{    new Operand("[*12]", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{     new Operand("[-A]", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{    new Operand("[A B]", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{     new Operand("[A + B]", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{    new Operand("[A + -1]", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{  new Operand("[A + ]", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{    new Operand("[]", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{    new Operand("[A+A+]", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
|         try{    new Operand("[A+[1]]", labels, registerSet, 0); } catch (InvalidOperandException e){} | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         try{   new Operand("a1", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{   new Operand("a_", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{   new Operand("_a", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{   new Operand("_1", labels, registerSet, 0); } catch (InvalidOperandException ignored){        } | ||||
|         try{    new Operand("S", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{   new Operand("label1_", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{   new Operand("+label1", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{    new Operand("[- 12]", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{    new Operand("[12+1]", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{    new Operand("[+label1", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{    new Operand("[*12]", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{     new Operand("[-A]", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{    new Operand("[A B]", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{     new Operand("[A + B]", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{    new Operand("[A + -1]", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{  new Operand("[A + ]", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{    new Operand("[]", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{    new Operand("[A+A+]", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|         try{    new Operand("[A+[1]]", labels, registerSet, 0); } catch (InvalidOperandException ignored){} | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user