You are to write a translator for a Very Simple Machine (VSM not to be confused with VMS!).
VSM has 8 16-bit registers that are named 0, 1, 2, ... 7. Memory is also organized as words of 16-bits. All arithmetic and boolean operations only work on registers. In other words, in order to work on a value stored in memory, it must first be loaded into a register, and in order to save a value to memory, the result must be calculated in a register and then stored into memory.
IMMEDIATE values can be symbolic addresses (names), or numbers. If they are numbers, the default base is base 10. By placing an 'h' after a number it will be assumed to be hex. For decimal numbers, you may use a - sign to indicate that the number is negative, eg. -1. For hex, you must use 2's complement to represent a negative. There are no # signs in VSM.
Here are the instructions that VSM understands.
ADD DEST, SRCA, SRCB DEST = SRCA + SRCB Add SRCB to SRCA store result in DEST. Affects all four condition codes: O, V, Z, N. All operands are registers.
AND DEST, SRCA, SRCB DEST = SRCA AND SRCB Perform Boolean AND of SRCB with SRCA store result in DEST. Affects condition codes N and Z; clears O and V. All operands are registers.
NOT DEST, SRCB DEST = NOT SRCB Perform Boolean NOT of SRCB store result in DEST. Affects condition codes N and Z; clears O and V. All operands are registers.
MOV DEST, SRCA DEST = SRCA Copy SRCA to DEST. Affects condition codes N and Z; clears O and V. All operands are registers.
MOVI DEST, IMMEDIATE DEST = IMMEDIATE Copy IMMEDIATE value to DEST. Affects condition codes N and Z; clears O and V. DEST is a register, IMMEDIATE is a number or a symbolic constant.
LSH DEST, SRCA DEST = LSH SRCA Shift SRCA 1 bit to the left store result in DEST, fill with 0. Affects condition codes N, Z and O; clears V. All operands are registers.
RSH DEST, SRCA DEST = RSH SRCA Shift SRCA 1 bit to the right store result in DEST, fill with 0. Affects condition codes N and Z; clears O and V. All operands are registers. LOAD DEST, IMMEDIATE Read the value from memory that is stored at the address held in IMMEDIATE. Store the result in DEST. DEST is a register, IMMEDIATE is a number or a symbolic constant, representing an address in memory. Affects condition codes N and Z; clears O and V.
SAVE IMMEDIATE, SRCA Write the value in SRCA to the memory location whose address is the value of IMMEDIATE. DEST is a register, IMMEDIATE is a number or a symbolic constant, representing an address in memory. Doesn't affect any condition codes. JMP IMMEDIATE Jump to the address IMMEDIATE. Doesn't affect any condition codes. JMPZ IMMEDIATE Jump to the address IMMEDIATE if the results of the last operation was zero. Doesn't affect any condition codes. JMPN IMMEDIATE Jump to the address IMMEDIATE if the results of the last operation was negative. Doesn't affect any condition codes. JMPO IMMEDIATE Jump to the address IMMEDIATE if the results of the last operation caused an unsigned overflow. Doesn't affect any condition codes. JMPV IMMEDIATE Jump to the address IMMEDIATE if the results of the last operation caused a signed overflow. Doesn't affect any condition codes. IMMEDIATE: This is the target of a jump. A label can precede any statement or can appear on a line by itself. The ':' must directly follow the IMMEDIATE value (this makes it easier for you to parse).
It has been decided by the system analyst (me) that this language is too tedious to use for programming, however the hardware will not be redesigned. So, the programmer (you) has been instructed to create a translator that will translate a language that is Much Better Intuitively (MBI) into the above language. Here are the instructions that MBI will understand.
ADD X, Y X = X + Y SUB X, Y X = X - Y. Subtraction is performed by using 2's complenent. MUL X, Y X = X * Y. Repeated addition will be fine for this. Assume each number is between -128 and 127. So, you need to worry about the sign. NOT X X = NOT X AND X, Y X = X AND Y OR X, Y X = X OR Y. Use some Boolean Algebra to rewrite this using only ANDs and NOTs. XOR X, Y X = X XOR Y. Use some Boolean Algebra to rewrite this using only ANDs and NOTs. MOV X, Y X = Y SHL X, Y Shift Y to the left X number of places. Fill vacated bits with zeroes. ASHR X, Y Shift Y to the right X number of places. Fill vacated bits with copies of the sign bit. LSHR X, Y Shift Y to the right X number of places. Fill vacated bits with zeroes. BGU LABEL Branch to the given label if X > Y as unsigned numbers. The X and Y would be from the previous arithmetic instruction. BLU LABEL Branch to the given label if X < Y as unsigned numbers. The X and Y would be from the previous arithmetic instruction. BGS LABEL Branch to the given label if X > Y as signed numbers. The X and Y would be from the previous arithmetic instruction. BLS LABEL Branch to the given label if X < Y as signed numbers. The X and Y would be from the previous arithmetic instruction. BEQ LABEL Branch to the given label if X = Y. The X and Y would be from the previous arithmetic instruction. BNEQ LABEL Branch to the given label if X <> Y.The X and Y would be from the previous arithmetic instruction. LABEL: This is the target of a branch. A label can precede any statement or can appear on a line by itself. The ':' must directly follow the LABEL value (this makes it easier for you to parse).
An MBI program cannot access any of the registers of the VSM machine. For ADD, SUB, MUL, OR, XOR the second operand can be a symbolic address, an address or an immeditae value. For CMP either operand or both can be a symbolic address, an address or an immediate value. For the shift instructions, the first operand may be a symbolic address, an address or an immediate value. All immediate values will be preceded by the # sign in VSM, otherwise they will be considered addresses. MBI immediate values do not have a # sign.
Your translator should read a file that is written in MBI and translate it to a program in VSM. Be sure that you don't duplicate any labels in the VSM program. For instance, if there is more than one BGS instruction in the MBI program, be sure that all the labels are unique in the VSM program.
For each language, there will only be one instruction per line. You may use symbolic addresses in each language. Do not be concerned with where these symbolic addresses are created. Assume that some other module will be handling the symbol table. If there is a symbolic address in the MBI program, then use the same symbolic address in the VSM program.
Notice that in the VSM language, all instructions work on registers, except for the instructions MOVI, LOAD, STORE and all the JMP instructions. When referencing a register, just use the number for the register: 0, 1, 2, ... 7.
If an MBI instruction contains a symbolic address, like NUM, as a source then in VSM you must first LOAD the value from NUM into a register. If the symbolic address is used as a destination, then you must STORE the contents of the register into memory at NUM.
Do not be too concerned about multiplying large numbers. Just write the routine to perform multiplication for two numbers that are both between -127 and 128. This way you will avoid the problem of having a result that won't fit in a register.
I will provide a test program at a later date. Test the program using your own test program until that time.