Fix labels and jumps

This commit is contained in:
2025-02-11 12:29:11 +01:00
parent f8b0307949
commit 0fc4040ad7
4 changed files with 57 additions and 139 deletions

View File

@@ -32,7 +32,7 @@ int lookupLabel(const char *name) {
}
// Add a label to the table
int addLabel(const char *name, int address) {
int addLabel(const char *name, uint32_t address) {
if (labelCount >= MAX_LABELS) {
fprintf(stderr, "Too many labels!\n");
return 1;
@@ -316,139 +316,30 @@ void firstPass(const char *source) {
continue;
strcpy(line, rest);
}
}
// // Parse the mnemonic and operands.
// char mnemonic[32], operand1[64], operand2[64], operand3[64];
// operand1[0] = '\0';
// operand2[0] = '\0';
// int tokenCount = sscanf(line, "%31s %63[^ ] %63[^ ] %63s",
// mnemonic, operand1, operand2, operand3);
//
//
// // Use the mapper to get a base opcode.
// int baseOpcode = getOpcode(mnemonic);
// if (baseOpcode == -1) {
// printf("Unknown instruction: %s\n", mnemonic);
// continue;
// }
//
// int size = CPU_INSTRUCTION_SIZE; // Instruction size in bytes.
// if (baseOpcode == -2) {
// // MOV instruction requires further resolution.
// int resolvedOpcode = resolveMOV(operand1, operand2);
// if (resolvedOpcode == MOV_RN_IMM || resolvedOpcode == MOV_RN_RM) {
// size = 3; // opcode (1) + reg (1) + immediate or register (1)
// } else if (resolvedOpcode == MOV_RN_ADDR || resolvedOpcode == MOV_ADDR_RN) {
// size = 6; // opcode (1) + one operand as register (1) and one 32-bit address (4) [+ padding if needed]
// } else {
// size = 3; // fallback
// }
// } else if (baseOpcode < 0) {
// // Ambiguous instructions that use resolveALU.
// // For JMP and jump-bit instructions, the jump target is in operand1.
// if (baseOpcode == -11) {
// // JMP: if operand1 starts with '+' or '-', it's relative.
// if (operand1[0] == '+' || operand1[0] == '-') {
// // resolve as JMP_REL.
// int resolvedOpcode = resolveALU(baseOpcode, operand1);
// size = 2; // opcode (1) + 1-byte relative offset (1)
// } else {
// int resolvedOpcode = resolveALU(baseOpcode, operand1);
// size = 5; // opcode (1) + 32-bit absolute address (4)
// }
// } else if (baseOpcode == -14 || baseOpcode == -15) {
// // JMPBS or JMPBC (jump if bit set/clear)
// int resolvedOpcode = resolveALU(baseOpcode, operand1);
// if (operand1[0] == 'R' || operand1[0] == 'r')
// size = 7; // opcode (1) + register (1) + bit (1) + 32-bit jump address (4)
// else
// size = 10; // opcode (1) + 32-bit memory address (4) + bit (1) + 32-bit jump address (4)
// } else {
// // For arithmetic ALU instructions and INC/DEC,
// // use operand2 to resolve.
// int resolvedOpcode = resolveALU(baseOpcode, operand2);
// switch (resolvedOpcode) {
// case ADD_RN_RM:
// case SUB_RN_RM:
// case MUL_RN_RM:
// case DIV_RN_RM:
// case MOD_RN_RM:
// case AND_RN_RM:
// case OR_RN_RM:
// case XOR_RN_RM:
// case ADD_RN_IMM:
// case SUB_RN_IMM:
// case MUL_RN_IMM:
// case DIV_RN_IMM:
// case MOD_RN_IMM:
// case AND_RN_IMM:
// case OR_RN_IMM:
// case XOR_RN_IMM:
// size = 3; // opcode (1) + register (1) + reg/immediate (1)
// break;
// case INC_RN:
// case DEC_RN:
// size = 2; // opcode (1) + register (1)
// break;
// case INC_ADDR:
// case DEC_ADDR:
// size = 5; // opcode (1) + 32-bit address (4)
// break;
// default:
// size = 3;
// break;
// }
// }
// } else {
// // Non-ambiguous instructions that have positive opcodes.
// // Use the mapping value (baseOpcode) directly.
// switch (baseOpcode) {
// case NOP:
// case BRK:
// case HLT:
// size = 1;
// break;
// case SWAP:
// case CMP:
// size = 3;
// break;
// case SWAPN:
// case NEG_RN:
// case NOT_RN:
// size = 2;
// break;
// case SHL_RN_IMM:
// case SHR_RN_IMM:
// case SAR_RN_IMM:
// size = 3;
// break;
// case JE:
// case JNE:
// case JG:
// case JL:
// case JGE:
// case JLE:
// case CALL:
// size = 5; // opcode (1) + 32-bit address (4)\n break;
// case RET:
// size = 1;
// break;
// default:
// size = 3;
// break;
// }
// }
// addr += size;
// }
// return addr;
// Parse the mnemonic and operands.
char mnemonic[32], operand1[64], operand2[64], operand3[64];
operand1[0] = '\0';
operand2[0] = '\0';
sscanf(line, "%31s %63[^ ] %63[^ ] %63s",
mnemonic, operand1, operand2, operand3);
// Use the mapper to get a base opcode.
int baseOpcode = getOpcode(mnemonic);
if (baseOpcode == -1) {
printf("Unknown instruction: %s\n", mnemonic);
continue;
}
addr += CPU_INSTRUCTION_SIZE;
}
}
//
// The second pass actually translates the assembly instructions to machine code.
// The machine code is written into the provided buffer. (It must be large enough.)
//
int completePass(const char *source, CPU *cpu, bool erase) {
uint32_t completePass(const char *source, CPU *cpu, bool erase) {
if (erase) {
memset(cpu->memory, 0, sizeof(cpu->memory));
memset(cpu->regs, 0, sizeof(cpu->regs));
@@ -488,8 +379,8 @@ int completePass(const char *source, CPU *cpu, bool erase) {
// Parse mnemonic and up to three operands.
char mnemonic[32], operand1[64], operand2[64], operand3[64];
mnemonic[0] = operand1[0] = operand2[0] = operand3[0] = '\0';
int tokenCount = sscanf(line, "%31s %63[^ ] %63[^ ] %63s",
mnemonic, operand1, operand2, operand3);
sscanf(line, "%31s %63[^ ] %63[^ ] %63s",
mnemonic, operand1, operand2, operand3);
// (Optionally, you might trim each operand individually here.)
@@ -733,5 +624,6 @@ int completePass(const char *source, CPU *cpu, bool erase) {
lineIndex++;
}
cpu->programEnd = addr;
return addr;
}

View File

@@ -24,7 +24,7 @@
//
typedef struct {
char name[64];
int address; // address (in the output machine code)
uint32_t address; // address (in the output machine code)
} Label;
extern Label labels[MAX_LABELS];
@@ -43,7 +43,7 @@ void toLowerCase(char *string);
int lookupLabel(const char *name);
// Add a label to the table
int addLabel(const char *name, int address);
int addLabel(const char *name, uint32_t address);
//
// Parse a register string (e.g., "R0", "R1", etc.) and return it's number.
@@ -83,7 +83,7 @@ void firstPass(const char *source);
// The second pass actually translates the assembly instructions to machine code.
// The machine code is written into the provided buffer. (It must be large enough.)
//
int completePass(const char *input, CPU *cpu, bool erase);
uint32_t completePass(const char *input, CPU *cpu, bool erase);
#endif //RISCB_ASSEMBLER_H

View File

@@ -9,7 +9,7 @@
// Initialize CPU
void init_cpu(CPU *cpu) {
memset(cpu, 0, sizeof(CPU));
cpu->mode = CPU_MODE_HALTED;
cpu->mode = CPU_MODE_HALTED | CPU_MODE_SECOND;
}
// Helper function for setting flags in the CPU (here we assume bit0 is the Zero flag,
@@ -27,7 +27,7 @@ void step(CPU *cpu) {
if (cpu->mode & (CPU_MODE_HALTED | CPU_MODE_PAUSED | CPU_MODE_ERROR)) {
return;
}
if (cpu->pc >= MEM_SIZE) {
if (cpu->pc >= MEM_SIZE || cpu->pc >= cpu->programEnd) {
if (cpu->mode | CPU_MODE_LOOP) {
cpu->pc = 0;
} else {
@@ -385,8 +385,11 @@ void step(CPU *cpu) {
if (bit > 7) {
bit = 7;
}
if (temp & (1 << bit))
if (temp & (1 << bit)) {
cpu->pc = newPC;
break;
}
cpu->pc += CPU_INSTRUCTION_SIZE;
break;
case JMP_BIT_SET_ADDR: {
@@ -400,8 +403,11 @@ void step(CPU *cpu) {
bit = 7;
}
newPC = read_address_argument(cpu);
if (read_mem(cpu, addrTemp) & (1 << bit))
if (read_mem(cpu, addrTemp) & (1 << bit)) {
cpu->pc = newPC;
break;
}
cpu->pc += CPU_INSTRUCTION_SIZE;
break;
}
@@ -409,8 +415,11 @@ void step(CPU *cpu) {
case JE: {
// Jump if equal (Zero flag set)
newPC = read_address_argument(cpu);
if (cpu->flags & CPU_FLAG_ZERO)
if (cpu->flags & CPU_FLAG_ZERO) {
cpu->pc = newPC;
break;
}
cpu->pc += CPU_INSTRUCTION_SIZE;
break;
}
@@ -423,8 +432,11 @@ void step(CPU *cpu) {
bit = 7;
}
newPC = read_address_argument(cpu);
if (!(temp & (1 << bit)))
if (!(temp & (1 << bit))) {
cpu->pc = newPC;
break;
}
cpu->pc += CPU_INSTRUCTION_SIZE;
break;
}
@@ -436,8 +448,11 @@ void step(CPU *cpu) {
bit = 7;
}
newPC = read_address_argument(cpu);
if (!(read_mem(cpu, addrTemp) & (1 << bit)))
if (!(read_mem(cpu, addrTemp) & (1 << bit))) {
cpu->pc = newPC;
break;
}
cpu->pc += CPU_INSTRUCTION_SIZE;
break;
}
@@ -446,7 +461,9 @@ void step(CPU *cpu) {
newPC = read_address_argument(cpu);
if (!(cpu->flags & CPU_FLAG_ZERO)) {
cpu->pc = newPC;
break;
}
cpu->pc += CPU_INSTRUCTION_SIZE;
break;
}
@@ -455,7 +472,9 @@ void step(CPU *cpu) {
newPC = read_address_argument(cpu);
if (!(cpu->flags & CPU_FLAG_NEGATIVE) && !(cpu->flags & CPU_FLAG_ZERO)) {
cpu->pc = newPC;
break;
}
cpu->pc += CPU_INSTRUCTION_SIZE;
break;
}
@@ -464,7 +483,9 @@ void step(CPU *cpu) {
newPC = read_address_argument(cpu);
if (cpu->flags & CPU_FLAG_NEGATIVE) {
cpu->pc = newPC;
break;
}
cpu->pc += CPU_INSTRUCTION_SIZE;
break;
}
@@ -473,7 +494,9 @@ void step(CPU *cpu) {
newPC = read_address_argument(cpu);
if ((cpu->flags & CPU_FLAG_ZERO) || !(cpu->flags & CPU_FLAG_NEGATIVE)) {
cpu->pc = newPC;
break;
}
cpu->pc += CPU_INSTRUCTION_SIZE;
break;
}
@@ -482,7 +505,9 @@ void step(CPU *cpu) {
newPC = read_address_argument(cpu);
if ((cpu->flags & CPU_FLAG_NEGATIVE) || (cpu->flags & CPU_FLAG_ZERO)) {
cpu->pc = newPC;
break;
}
cpu->pc += CPU_INSTRUCTION_SIZE;
break;
}

View File

@@ -35,6 +35,7 @@ typedef struct {
uint32_t pc; // Program counter
uint32_t stack_ptr; // Stack pointer
uint8_t flags; // Status flags
uint32_t programEnd;
uint8_t mode;
uint32_t cycle;
} CPU;