diff --git a/assembler/assembler.c b/assembler/assembler.c index 4d20403..aa6aa32 100644 --- a/assembler/assembler.c +++ b/assembler/assembler.c @@ -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; } \ No newline at end of file diff --git a/assembler/assembler.h b/assembler/assembler.h index 073143d..9c31a43 100644 --- a/assembler/assembler.h +++ b/assembler/assembler.h @@ -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 diff --git a/cpu/core.c b/cpu/core.c index db65cb7..e120dbd 100644 --- a/cpu/core.c +++ b/cpu/core.c @@ -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; } diff --git a/cpu/core.h b/cpu/core.h index ffe39c9..69db860 100644 --- a/cpu/core.h +++ b/cpu/core.h @@ -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;