Some changes

This commit is contained in:
2025-02-16 17:28:10 +01:00
parent 0fc4040ad7
commit 4d3755e2ce
18 changed files with 562 additions and 80 deletions

View File

@@ -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;