Some changes
This commit is contained in:
@@ -90,6 +90,9 @@ void toUpperCase(char *string) {
|
||||
if (*string > 0x60 && *string < 0x7b) {
|
||||
(*string) -= 0x20;
|
||||
}
|
||||
if (*string == '\r') {
|
||||
*string = ' ';
|
||||
}
|
||||
string++;
|
||||
}
|
||||
}
|
||||
@@ -117,7 +120,7 @@ int getOpcode(char *mnemonic) {
|
||||
else if (strcmp(mnemonic, "HLT") == 0)
|
||||
return HLT;
|
||||
else if (strcmp(mnemonic, "MOV") == 0)
|
||||
return -2; // Special case: we must decide between MOV_RN_IMM, MOV_RN_RM, MOV_RN_ADDR, MOV_ADDR_RN
|
||||
return -2; // Special case: we must decide between MOV_IMM_RN, MOV_RN_RM, MOV_RN_ADDR, MOV_ADDR_RN
|
||||
else if (strcmp(mnemonic, "SWAP") == 0)
|
||||
return SWAP;
|
||||
else if (strcmp(mnemonic, "SWAPN") == 0)
|
||||
@@ -161,9 +164,13 @@ int getOpcode(char *mnemonic) {
|
||||
else if (strcmp(mnemonic, "JNE") == 0)
|
||||
return JNE;
|
||||
else if (strcmp(mnemonic, "JMPBS") == 0)
|
||||
return -14; //Special: decide between JMP_BIT_SET_RN and JMP_BIT_SET_ADDR
|
||||
return -14; //Special: decide between BIT_TS_RN and BIT_TS_ADDR
|
||||
else if (strcmp(mnemonic, "JMPBC") == 0)
|
||||
return -15; //Special: decide between JMP_BIT_CLEAR_RN and JMP_BIT_CLEAR_ADDR
|
||||
return -15; //Special: decide between BIT_TC_RN and BIT_TC_ADDR
|
||||
else if (strcmp(mnemonic, "BITS") == 0)
|
||||
return -16; //Special: decide between BITS_RN and BITS_ADDR
|
||||
else if (strcmp(mnemonic, "BITC") == 0)
|
||||
return -17; //Special: decide between BITC_RN and BITC_ADDR
|
||||
else if (strcmp(mnemonic, "JG") == 0)
|
||||
return JG;
|
||||
else if (strcmp(mnemonic, "JL") == 0)
|
||||
@@ -186,20 +193,20 @@ int getOpcode(char *mnemonic) {
|
||||
// based on the type of the operand (register vs. immediate vs. memory).
|
||||
// The following helper functions decide that, given two operands (as strings).
|
||||
//
|
||||
// For example, "MOV Rn, 42" should choose MOV_RN_IMM, while "MOV Rn, Rm" should choose MOV_RN_RM.
|
||||
// For example, "MOV Rn, 42" should choose MOV_IMM_RN, while "MOV Rn, Rm" should choose MOV_RN_RM.
|
||||
// We assume that memory addresses are written in square brackets, e.g. "[123]".
|
||||
//
|
||||
int resolveMOV(const char *dest, const char *src) {
|
||||
// If dest starts with '[' then it is a memory destination.
|
||||
if (dest[0] == '[') return MOV_ADDR_RN; // actually, MOV [Addr], Rn expects Rn in second operand
|
||||
if (dest[0] == '[') return MOV_RN_ADDR; // actually, MOV [Addr], Rn expects Rn in second operand
|
||||
// Otherwise, dest is a register.
|
||||
// Now, check src:
|
||||
if (src[0] == 'R' || src[0] == 'r') {
|
||||
if ((dest[0] == 'R' || dest[0] == 'r') && (src[0] == 'R' || src[0] == 'r')) {
|
||||
return MOV_RN_RM;
|
||||
} else if (src[0] == '[') {
|
||||
return MOV_RN_ADDR;
|
||||
return MOV_ADDR_RN;
|
||||
} else {
|
||||
return MOV_RN_IMM;
|
||||
return MOV_IMM_RN;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,9 +235,13 @@ int resolveALU(int baseOpcode, const char *src) {
|
||||
case -13:
|
||||
return DEC_RN;
|
||||
case -14:
|
||||
return JMP_BIT_SET_RN;
|
||||
return BIT_TS_RN;
|
||||
case -15:
|
||||
return JMP_BIT_CLEAR_RN;
|
||||
return BIT_TC_RN;
|
||||
case -16:
|
||||
return BITS_RN;
|
||||
case -17:
|
||||
return BITC_RN;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@@ -266,9 +277,13 @@ int resolveALU(int baseOpcode, const char *src) {
|
||||
case -13:
|
||||
return DEC_ADDR;
|
||||
case -14:
|
||||
return JMP_BIT_SET_ADDR;
|
||||
return BIT_TS_ADDR;
|
||||
case -15:
|
||||
return JMP_BIT_CLEAR_ADDR;
|
||||
return BIT_TC_ADDR;
|
||||
case -16:
|
||||
return BITS_ADDR;
|
||||
case -17:
|
||||
return BITC_ADDR;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@@ -367,6 +382,17 @@ uint32_t completePass(const char *source, CPU *cpu, bool erase) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Stop at the first semicolon.
|
||||
char *semicolon = strchr(line, ';');
|
||||
if (semicolon != NULL) {
|
||||
*semicolon = '\0'; // Terminate the string at the semicolon
|
||||
trim(line); // Trim again in case spaces remain
|
||||
if (line[0] == '\0') {
|
||||
lineIndex++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any label definitions (up to the colon).
|
||||
char *colon = strchr(line, ':');
|
||||
if (colon != NULL) {
|
||||
@@ -398,31 +424,20 @@ uint32_t completePass(const char *source, CPU *cpu, bool erase) {
|
||||
fprintf(stderr, "Error: MOV requires two operands.\n");
|
||||
return 1;
|
||||
}
|
||||
int resolvedOpcode = resolveMOV(operand1, operand2);
|
||||
int resolvedOpcode = resolveMOV(operand2, operand1);
|
||||
cpu->memory[addr++] = resolvedOpcode;
|
||||
if (resolvedOpcode == MOV_RN_IMM) {
|
||||
int reg = parseRegister(operand1);
|
||||
uint8_t imm = parseImmediate(operand2);
|
||||
cpu->memory[addr++] = reg;
|
||||
if (resolvedOpcode == MOV_IMM_RN) {
|
||||
uint8_t imm = parseImmediate(operand1);
|
||||
int reg = parseRegister(operand2);
|
||||
cpu->memory[addr++] = imm;
|
||||
} else if (resolvedOpcode == MOV_RN_RM) {
|
||||
int regDest = parseRegister(operand1);
|
||||
int regSrc = parseRegister(operand2);
|
||||
cpu->memory[addr++] = regDest;
|
||||
cpu->memory[addr++] = regSrc;
|
||||
} else if (resolvedOpcode == MOV_RN_ADDR) {
|
||||
int reg = parseRegister(operand1);
|
||||
// Assume source is written as "[address]": remove the brackets.
|
||||
char addrStr[32];
|
||||
strncpy(addrStr, operand2 + 1, strlen(operand2) - 2);
|
||||
addrStr[strlen(operand2) - 2] = '\0';
|
||||
uint32_t memAddr = (uint32_t) strtoul(addrStr, NULL, 0);
|
||||
cpu->memory[addr++] = reg;
|
||||
cpu->memory[addr++] = memAddr & 0xFF;
|
||||
cpu->memory[addr++] = (memAddr >> 8) & 0xFF;
|
||||
cpu->memory[addr++] = (memAddr >> 16) & 0xFF;
|
||||
} else if (resolvedOpcode == MOV_RN_RM) {
|
||||
int regSrc = parseRegister(operand1);
|
||||
int regDest = parseRegister(operand2);
|
||||
cpu->memory[addr++] = regSrc;
|
||||
cpu->memory[addr++] = regDest;
|
||||
} else if (resolvedOpcode == MOV_ADDR_RN) {
|
||||
// Destination is memory (written as "[address]").
|
||||
// Assume source is written as "[address]": remove the brackets.
|
||||
char addrStr[32];
|
||||
strncpy(addrStr, operand1 + 1, strlen(operand1) - 2);
|
||||
addrStr[strlen(operand1) - 2] = '\0';
|
||||
@@ -432,6 +447,17 @@ uint32_t completePass(const char *source, CPU *cpu, bool erase) {
|
||||
cpu->memory[addr++] = (memAddr >> 8) & 0xFF;
|
||||
cpu->memory[addr++] = (memAddr >> 16) & 0xFF;
|
||||
cpu->memory[addr++] = reg;
|
||||
} else if (resolvedOpcode == MOV_RN_ADDR) {
|
||||
// Destination is memory (written as "[address]").
|
||||
char addrStr[32];
|
||||
strncpy(addrStr, operand2 + 1, strlen(operand2) - 2);
|
||||
addrStr[strlen(operand2) - 2] = '\0';
|
||||
int reg = parseRegister(operand1);
|
||||
uint32_t memAddr = (uint32_t) strtoul(addrStr, NULL, 0);
|
||||
cpu->memory[addr++] = reg;
|
||||
cpu->memory[addr++] = memAddr & 0xFF;
|
||||
cpu->memory[addr++] = (memAddr >> 8) & 0xFF;
|
||||
cpu->memory[addr++] = (memAddr >> 16) & 0xFF;
|
||||
}
|
||||
}
|
||||
// --- INC and DEC (baseOpcode == -12 or -13) ---
|
||||
@@ -465,7 +491,7 @@ uint32_t completePass(const char *source, CPU *cpu, bool erase) {
|
||||
fprintf(stderr, "Error: %s requires two operands.\n", mnemonic);
|
||||
return 1;
|
||||
}
|
||||
int resolvedOpcode = resolveALU(baseOpcode, operand2);
|
||||
int resolvedOpcode = resolveALU(baseOpcode, operand1);
|
||||
cpu->memory[addr++] = resolvedOpcode;
|
||||
int regDest = parseRegister(operand1);
|
||||
cpu->memory[addr++] = regDest;
|
||||
@@ -617,7 +643,7 @@ uint32_t completePass(const char *source, CPU *cpu, bool erase) {
|
||||
}
|
||||
const uint32_t remainingBytes = CPU_INSTRUCTION_SIZE - (addr - oldAddr);
|
||||
if (remainingBytes > CPU_INSTRUCTION_SIZE) {
|
||||
printf("HELP, INSTRUCTION SIZE SMALLER THAN INSTRUCTION");
|
||||
printf("HELP, INSTRUCTION SIZE SMALLER THAN INSTRUCTION\n");
|
||||
}
|
||||
cpu->addrToLineMapper[(addr - (addr % CPU_INSTRUCTION_SIZE)) / CPU_INSTRUCTION_SIZE] = lineIndex;
|
||||
addr += remainingBytes;
|
||||
|
Reference in New Issue
Block a user