add more feature and test case
This commit is contained in:
parent
119ebdd89c
commit
82b0e6110f
33
Makefile
33
Makefile
@ -4,6 +4,14 @@ SRC_ASSEMBLER = assembler.c
|
||||
SRC_ASM_PARSER = asm_parser.c
|
||||
OBJ_ASM_PARSER = asm_parser.o
|
||||
TARGET = assembler
|
||||
|
||||
VALID_DIR = test_case/valid
|
||||
INVALID_DIR = test_case/invalid
|
||||
VALID_ASM_FILES := $(wildcard $(VALID_DIR)/*.asm)
|
||||
INVALID_ASM_FILES := $(wildcard $(INVALID_DIR)/*.asm)
|
||||
|
||||
VALID_OBJ_FILES := $(VALID_ASM_FILES:.asm=.obj)
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
assembler: $(OBJ_ASM_PARSER) $(SRC_ASSEMBLER)
|
||||
@ -12,6 +20,31 @@ assembler: $(OBJ_ASM_PARSER) $(SRC_ASSEMBLER)
|
||||
asm_parser.o: $(SRC_ASM_PARSER)
|
||||
$(CC) $(CFLAGS) -c $(SRC_ASM_PARSER)
|
||||
|
||||
test-valid: $(TARGET)
|
||||
@for file in $(VALID_ASM_FILES); do \
|
||||
echo "Testing valid case $$file..."; \
|
||||
if ./$(TARGET) $$file 0; then \
|
||||
echo "Assembler completed $$file"; \
|
||||
else \
|
||||
echo "Assembler reported an error for $$file"; \
|
||||
fi \
|
||||
done
|
||||
@echo "All valid test cases assembled successfully."
|
||||
|
||||
test-invalid: $(TARGET)
|
||||
@for file in $(INVALID_ASM_FILES); do \
|
||||
echo "Testing invalid case $$file..."; \
|
||||
if ./$(TARGET) $$file 2 > null; then \
|
||||
echo "Error: Assembler did not report an error for $$file"; \
|
||||
exit 1; \
|
||||
else \
|
||||
echo "Assembler correctly reported an error for $$file"; \
|
||||
fi \
|
||||
done
|
||||
|
||||
test: $(TARGET) test-valid test-invalid
|
||||
@echo "All tests completed."
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ_ASM_PARSER)
|
||||
|
||||
|
||||
754
asm_parser.c
754
asm_parser.c
@ -176,6 +176,75 @@ int parse_instruction(char *instr, char *instr_bin_str) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return ret;
|
||||
} else if (strcmp(tokens[0], "NOP") == 0) {
|
||||
int ret = parse_nop(instr, instr_bin_str);
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return ret;
|
||||
} else if (strcmp(tokens[0], "NOT") == 0) {
|
||||
int ret = parse_not(instr, instr_bin_str);
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return ret;
|
||||
} else if (strcmp(tokens[0], "CONST") == 0) {
|
||||
int ret = parse_const(instr, instr_bin_str);
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return ret;
|
||||
} else if (strcmp(tokens[0], "SLL") == 0) {
|
||||
int ret = parse_sll(instr, instr_bin_str);
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return ret;
|
||||
} else if (strcmp(tokens[0], "SRA") == 0) {
|
||||
int ret = parse_sra(instr, instr_bin_str);
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return ret;
|
||||
} else if (strcmp(tokens[0], "SRL") == 0) {
|
||||
int ret = parse_srl(instr, instr_bin_str);
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return ret;
|
||||
} else if (strcmp(tokens[0], "MOD") == 0) {
|
||||
int ret = parse_mod(instr, instr_bin_str);
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return ret;
|
||||
} else if (strcmp(tokens[0], "JMPR") == 0) {
|
||||
int ret = parse_jmpr(instr, instr_bin_str);
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return ret;
|
||||
} else if (strcmp(tokens[0], "TRAP") == 0) {
|
||||
int ret = parse_trap(instr, instr_bin_str);
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return ret;
|
||||
} else if (strcmp(tokens[0], "RTI") == 0) {
|
||||
int ret = parse_rti(instr, instr_bin_str);
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return ret;
|
||||
} else if (strcmp(tokens[0], "RET") == 0) {
|
||||
// RET is a pseudo-instruction equivalent to JMPR R7
|
||||
char expanded_instr[COLS];
|
||||
strcpy(expanded_instr, "JMPR R7");
|
||||
int ret = parse_jmpr(expanded_instr, instr_bin_str);
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
printf("error: parse_instruction failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
@ -1040,4 +1109,687 @@ int write_obj_file(char *filename, unsigned short int program_bin[ROWS], int ins
|
||||
}
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int parse_nop(char *, char *instr_bin_str) {
|
||||
// NOP: Opcode 0000000---------
|
||||
strcpy(instr_bin_str, "0000000");
|
||||
//
|
||||
strcat(instr_bin_str, "000000000");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_not(char *instr, char *instr_bin_str) {
|
||||
// Opcode: 0101
|
||||
strcpy(instr_bin_str, "0101"); // Opcode
|
||||
char instr_copy[COLS];
|
||||
strcpy(instr_copy, instr);
|
||||
char *tokens[10];
|
||||
int token_count = 0;
|
||||
char *p = instr_copy;
|
||||
while (*p != '\0') {
|
||||
while (isspace(*p) || *p == ',') p++;
|
||||
if (*p == '\0') break;
|
||||
char *start = p;
|
||||
while (*p != '\0' && !isspace(*p) && *p != ',') p++;
|
||||
size_t len = p - start;
|
||||
tokens[token_count] = (char *)malloc(len + 1);
|
||||
strncpy(tokens[token_count], start, len);
|
||||
tokens[token_count][len] = '\0';
|
||||
token_count++;
|
||||
}
|
||||
|
||||
if (token_count != 3) {
|
||||
printf("error: parse_not() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
to_uppercase(tokens[1]);
|
||||
to_uppercase(tokens[2]);
|
||||
|
||||
if (tokens[1][0] != 'R') {
|
||||
printf("error: parse_not() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char rd_num = tokens[1][1];
|
||||
int ret = parse_reg(rd_num, instr_bin_str);
|
||||
if (ret != 0) {
|
||||
printf("error: parse_not() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Parse Rs
|
||||
if (tokens[2][0] != 'R') {
|
||||
printf("error: parse_not() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char rs_num = tokens[2][1];
|
||||
ret = parse_reg(rs_num, instr_bin_str); // Rs
|
||||
if (ret != 0) {
|
||||
printf("error: parse_not() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
strcat(instr_bin_str, "001");
|
||||
strcat(instr_bin_str, "000");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_const(char *instr, char *instr_bin_str) {
|
||||
// Opcode: 1001
|
||||
strcpy(instr_bin_str, "1001");
|
||||
char instr_copy[COLS];
|
||||
strcpy(instr_copy, instr);
|
||||
char *tokens[10];
|
||||
int token_count = 0;
|
||||
char *p = instr_copy;
|
||||
while (*p != '\0') {
|
||||
while (isspace(*p) || *p == ',') p++;
|
||||
if (*p == '\0') break;
|
||||
char *start = p;
|
||||
while (*p != '\0' && !isspace(*p) && *p != ',') p++;
|
||||
size_t len = p - start;
|
||||
tokens[token_count] = (char *)malloc(len + 1);
|
||||
strncpy(tokens[token_count], start, len);
|
||||
tokens[token_count][len] = '\0';
|
||||
token_count++;
|
||||
}
|
||||
|
||||
if (token_count != 3) {
|
||||
printf("error: parse_const() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
to_uppercase(tokens[1]);
|
||||
to_uppercase(tokens[2]);
|
||||
|
||||
// Parse Rd
|
||||
if (tokens[1][0] != 'R') {
|
||||
printf("error: parse_const() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char rd_num = tokens[1][1];
|
||||
int ret = parse_reg(rd_num, instr_bin_str); // Rd
|
||||
if (ret != 0) {
|
||||
printf("error: parse_const() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Parse IMM9
|
||||
int imm_value;
|
||||
ret = parse_imm9(tokens[2], &imm_value);
|
||||
if (ret != 0) {
|
||||
printf("error: parse_const() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char imm_bits[10];
|
||||
int_to_bin_str(imm_value & 0x1FF, 9, imm_bits);
|
||||
strcat(instr_bin_str, imm_bits);
|
||||
|
||||
// Free allocated memory
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_imm9(char *imm_str, int *imm_value) {
|
||||
int value = 0;
|
||||
if (imm_str[0] == '#') {
|
||||
value = atoi(&imm_str[1]);
|
||||
} else if (imm_str[0] == 'x') {
|
||||
sscanf(&imm_str[1], "%x", &value);
|
||||
} else if (imm_str[0] == '0' && imm_str[1] == 'x') {
|
||||
sscanf(&imm_str[2], "%x", &value);
|
||||
} else {
|
||||
printf("error: invalid immediate value\n");
|
||||
return 4;
|
||||
}
|
||||
if (value < -256 || value > 255) {
|
||||
printf("error: immediate value out of range\n");
|
||||
return 4;
|
||||
}
|
||||
*imm_value = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_sll(char *instr, char *instr_bin_str) {
|
||||
// Opcode: 1010
|
||||
strcpy(instr_bin_str, "1010"); // Opcode bits [15:12]
|
||||
|
||||
// Tokenize the instruction line
|
||||
char instr_copy[COLS];
|
||||
strcpy(instr_copy, instr);
|
||||
char *tokens[10];
|
||||
int token_count = 0;
|
||||
char *p = instr_copy;
|
||||
while (*p != '\0') {
|
||||
// Skip spaces and commas
|
||||
while (isspace((unsigned char)*p) || *p == ',') p++;
|
||||
if (*p == '\0') break;
|
||||
|
||||
// Collect token
|
||||
char *start = p;
|
||||
while (*p != '\0' && !isspace((unsigned char)*p) && *p != ',') p++;
|
||||
size_t len = p - start;
|
||||
tokens[token_count] = (char *)malloc(len + 1);
|
||||
strncpy(tokens[token_count], start, len);
|
||||
tokens[token_count][len] = '\0';
|
||||
token_count++;
|
||||
}
|
||||
|
||||
if (token_count != 4) {
|
||||
printf("error: parse_sll() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Enforce uppercase for operands
|
||||
to_uppercase(tokens[1]);
|
||||
to_uppercase(tokens[2]);
|
||||
to_uppercase(tokens[3]);
|
||||
|
||||
// Parse Rd
|
||||
if (tokens[1][0] != 'R') {
|
||||
printf("error: parse_sll() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char rd_num = tokens[1][1];
|
||||
int ret = parse_reg(rd_num, instr_bin_str); // Rd
|
||||
if (ret != 0) {
|
||||
printf("error: parse_sll() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Parse Rs
|
||||
if (tokens[2][0] != 'R') {
|
||||
printf("error: parse_sll() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char rs_num = tokens[2][1];
|
||||
ret = parse_reg(rs_num, instr_bin_str); // Rs
|
||||
if (ret != 0) {
|
||||
printf("error: parse_sll() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Sub-opcode bits[5:4] = "00"
|
||||
strcat(instr_bin_str, "00");
|
||||
|
||||
// Parse UIMM4
|
||||
int uimm_value;
|
||||
ret = parse_uimm4(tokens[3], &uimm_value);
|
||||
if (ret != 0) {
|
||||
printf("error: parse_sll() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
// Append UIMM4 bits
|
||||
char uimm_bits[5];
|
||||
int_to_bin_str(uimm_value & 0xF, 4, uimm_bits);
|
||||
strcat(instr_bin_str, uimm_bits);
|
||||
|
||||
// Free allocated memory
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_sra(char *instr, char *instr_bin_str) {
|
||||
// Opcode: 1010
|
||||
strcpy(instr_bin_str, "1010"); // Opcode bits [15:12]
|
||||
|
||||
// Tokenize and parse similarly to parse_sll, but with sub-opcode "01"
|
||||
// Tokenize the instruction line
|
||||
char instr_copy[COLS];
|
||||
strcpy(instr_copy, instr);
|
||||
char *tokens[10];
|
||||
int token_count = 0;
|
||||
char *p = instr_copy;
|
||||
while (*p != '\0') {
|
||||
while (isspace((unsigned char)*p) || *p == ',') p++;
|
||||
if (*p == '\0') break;
|
||||
char *start = p;
|
||||
while (*p != '\0' && !isspace((unsigned char)*p) && *p != ',') p++;
|
||||
size_t len = p - start;
|
||||
tokens[token_count] = (char *)malloc(len + 1);
|
||||
strncpy(tokens[token_count], start, len);
|
||||
tokens[token_count][len] = '\0';
|
||||
token_count++;
|
||||
}
|
||||
|
||||
if (token_count != 4) {
|
||||
printf("error: parse_sra() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
to_uppercase(tokens[1]);
|
||||
to_uppercase(tokens[2]);
|
||||
to_uppercase(tokens[3]);
|
||||
|
||||
if (tokens[1][0] != 'R') {
|
||||
printf("error: parse_sra() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char rd_num = tokens[1][1];
|
||||
int ret = parse_reg(rd_num, instr_bin_str); // Rd
|
||||
if (ret != 0) {
|
||||
printf("error: parse_sra() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (tokens[2][0] != 'R') {
|
||||
printf("error: parse_sra() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char rs_num = tokens[2][1];
|
||||
ret = parse_reg(rs_num, instr_bin_str); // Rs
|
||||
if (ret != 0) {
|
||||
printf("error: parse_sra() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
// Sub-opcode bits[5:4] = "01"
|
||||
strcat(instr_bin_str, "01");
|
||||
|
||||
int uimm_value;
|
||||
ret = parse_uimm4(tokens[3], &uimm_value);
|
||||
if (ret != 0) {
|
||||
printf("error: parse_sra() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char uimm_bits[5];
|
||||
int_to_bin_str(uimm_value & 0xF, 4, uimm_bits);
|
||||
strcat(instr_bin_str, uimm_bits);
|
||||
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_srl(char *instr, char *instr_bin_str) {
|
||||
// Opcode: 1010
|
||||
strcpy(instr_bin_str, "1010"); // Opcode bits [15:12]
|
||||
|
||||
// Tokenize and parse similarly to parse_sll, but with sub-opcode "10"
|
||||
char instr_copy[COLS];
|
||||
strcpy(instr_copy, instr);
|
||||
char *tokens[10];
|
||||
int token_count = 0;
|
||||
char *p = instr_copy;
|
||||
while (*p != '\0') {
|
||||
while (isspace((unsigned char)*p) || *p == ',') p++;
|
||||
if (*p == '\0') break;
|
||||
char *start = p;
|
||||
while (*p != '\0' && !isspace((unsigned char)*p) && *p != ',') p++;
|
||||
size_t len = p - start;
|
||||
tokens[token_count] = (char *)malloc(len + 1);
|
||||
strncpy(tokens[token_count], start, len);
|
||||
tokens[token_count][len] = '\0';
|
||||
token_count++;
|
||||
}
|
||||
|
||||
if (token_count != 4) {
|
||||
printf("error: parse_srl() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
to_uppercase(tokens[1]);
|
||||
to_uppercase(tokens[2]);
|
||||
to_uppercase(tokens[3]);
|
||||
|
||||
if (tokens[1][0] != 'R') {
|
||||
printf("error: parse_srl() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char rd_num = tokens[1][1];
|
||||
int ret = parse_reg(rd_num, instr_bin_str); // Rd
|
||||
if (ret != 0) {
|
||||
printf("error: parse_srl() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (tokens[2][0] != 'R') {
|
||||
printf("error: parse_srl() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char rs_num = tokens[2][1];
|
||||
ret = parse_reg(rs_num, instr_bin_str); // Rs
|
||||
if (ret != 0) {
|
||||
printf("error: parse_srl() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Sub-opcode bits[5:4] = "10"
|
||||
strcat(instr_bin_str, "10");
|
||||
|
||||
int uimm_value;
|
||||
ret = parse_uimm4(tokens[3], &uimm_value);
|
||||
if (ret != 0) {
|
||||
printf("error: parse_srl() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char uimm_bits[5];
|
||||
int_to_bin_str(uimm_value & 0xF, 4, uimm_bits);
|
||||
strcat(instr_bin_str, uimm_bits);
|
||||
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_uimm4(char *imm_str, int *imm_value) {
|
||||
int value = 0;
|
||||
if (imm_str[0] == '#') {
|
||||
// Decimal immediate
|
||||
value = atoi(&imm_str[1]);
|
||||
} else if (imm_str[0] == 'x') {
|
||||
// Hex immediate
|
||||
sscanf(&imm_str[1], "%x", &value);
|
||||
} else if (imm_str[0] == '0' && imm_str[1] == 'x') {
|
||||
// Hex immediate
|
||||
sscanf(&imm_str[2], "%x", &value);
|
||||
} else {
|
||||
printf("error: invalid immediate value\n");
|
||||
return 4;
|
||||
}
|
||||
// Check if value fits in unsigned 4-bit
|
||||
if (value < 0 || value > 15) {
|
||||
printf("error: immediate value out of range\n");
|
||||
return 4;
|
||||
}
|
||||
*imm_value = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_mod(char *instr, char *instr_bin_str) {
|
||||
// Opcode: 1010
|
||||
strcpy(instr_bin_str, "1010"); // Opcode bits [15:12]
|
||||
|
||||
// Tokenize the instruction line
|
||||
char instr_copy[COLS];
|
||||
strcpy(instr_copy, instr);
|
||||
char *tokens[10];
|
||||
int token_count = 0;
|
||||
char *p = instr_copy;
|
||||
while (*p != '\0') {
|
||||
while (isspace((unsigned char)*p) || *p == ',') p++;
|
||||
if (*p == '\0') break;
|
||||
char *start = p;
|
||||
while (*p != '\0' && !isspace((unsigned char)*p) && *p != ',') p++;
|
||||
size_t len = p - start;
|
||||
tokens[token_count] = (char *)malloc(len + 1);
|
||||
strncpy(tokens[token_count], start, len);
|
||||
tokens[token_count][len] = '\0';
|
||||
token_count++;
|
||||
}
|
||||
|
||||
if (token_count != 4) {
|
||||
printf("error: parse_mod() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
to_uppercase(tokens[1]);
|
||||
to_uppercase(tokens[2]);
|
||||
to_uppercase(tokens[3]);
|
||||
|
||||
if (tokens[1][0] != 'R') {
|
||||
printf("error: parse_mod() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char rd_num = tokens[1][1];
|
||||
int ret = parse_reg(rd_num, instr_bin_str); // Rd
|
||||
if (ret != 0) {
|
||||
printf("error: parse_mod() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (tokens[2][0] != 'R') {
|
||||
printf("error: parse_mod() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char rs_num = tokens[2][1];
|
||||
ret = parse_reg(rs_num, instr_bin_str); // Rs
|
||||
if (ret != 0) {
|
||||
printf("error: parse_mod() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Sub-opcode bits[5:4] = "11", bit[3]: don't care, set to '0'
|
||||
strcat(instr_bin_str, "110");
|
||||
|
||||
if (tokens[3][0] != 'R') {
|
||||
printf("error: parse_mod() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char rt_num = tokens[3][1];
|
||||
ret = parse_reg(rt_num, instr_bin_str); // Rt
|
||||
if (ret != 0) {
|
||||
printf("error: parse_mod() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_jmpr(char *instr, char *instr_bin_str) {
|
||||
// Opcode: 11000
|
||||
strcpy(instr_bin_str, "11000"); // Opcode bits [15:11]
|
||||
|
||||
// bits[10:9]: don't cares, set to "00"
|
||||
strcat(instr_bin_str, "00");
|
||||
|
||||
// Tokenize the instruction line
|
||||
char instr_copy[COLS];
|
||||
strcpy(instr_copy, instr);
|
||||
char *tokens[10];
|
||||
int token_count = 0;
|
||||
char *p = instr_copy;
|
||||
|
||||
while (*p != '\0') {
|
||||
while (isspace((unsigned char)*p) || *p == ',') p++;
|
||||
if (*p == '\0') break;
|
||||
char *start = p;
|
||||
while (*p != '\0' && !isspace((unsigned char)*p) && *p != ',') p++;
|
||||
size_t len = p - start;
|
||||
tokens[token_count] = (char *)malloc(len + 1);
|
||||
strncpy(tokens[token_count], start, len);
|
||||
tokens[token_count][len] = '\0';
|
||||
token_count++;
|
||||
}
|
||||
|
||||
if (token_count != 2) {
|
||||
printf("error: parse_jmpr() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
to_uppercase(tokens[1]);
|
||||
|
||||
if (tokens[1][0] != 'R') {
|
||||
printf("error: parse_jmpr() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
char rs_num = tokens[1][1];
|
||||
int ret = parse_reg(rs_num, instr_bin_str); // Rs
|
||||
if (ret != 0) {
|
||||
printf("error: parse_jmpr() failed\n");
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
strcat(instr_bin_str, "000000");
|
||||
|
||||
for (int i = 0; i < token_count; i++) {
|
||||
free(tokens[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_trap(char *, char *instr_bin_str) {
|
||||
// Opcode: 1111
|
||||
strcpy(instr_bin_str, "1111"); // Opcode
|
||||
|
||||
// Bits[11:8] are don't cares, set to "0000"
|
||||
strcat(instr_bin_str, "0000");
|
||||
// Parse UIMM8
|
||||
int uimm_value;
|
||||
int ret = parse_uimm8("#0x80", &uimm_value);
|
||||
if (ret != 0) {
|
||||
printf("error: parse_trap() failed\n");
|
||||
return 4;
|
||||
}
|
||||
// Append UIMM8 bits
|
||||
char uimm_bits[9];
|
||||
int_to_bin_str(uimm_value & 0xFF, 8, uimm_bits);
|
||||
strcat(instr_bin_str, uimm_bits);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_uimm8(char *imm_str, int *imm_value) {
|
||||
int value = 0;
|
||||
if (imm_str[0] == '#') {
|
||||
// Decimal immediate
|
||||
value = atoi(&imm_str[1]);
|
||||
} else if (imm_str[0] == 'x') {
|
||||
// Hex immediate
|
||||
sscanf(&imm_str[1], "%x", &value);
|
||||
} else if (imm_str[0] == '0' && imm_str[1] == 'x') {
|
||||
// Hex immediate
|
||||
sscanf(&imm_str[2], "%x", &value);
|
||||
} else {
|
||||
printf("error: invalid immediate value\n");
|
||||
return 4;
|
||||
}
|
||||
// Check if value fits in unsigned 8-bit
|
||||
if (value < 0 || value > 255) {
|
||||
printf("error: immediate value out of range\n");
|
||||
return 4;
|
||||
}
|
||||
*imm_value = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_rti(char *, char *instr_bin_str) {
|
||||
strcpy(instr_bin_str, "1000"); // Opcode
|
||||
|
||||
strcat(instr_bin_str, "000000000000");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
28
asm_parser.h
28
asm_parser.h
@ -1,14 +1,3 @@
|
||||
/***************************************************************************
|
||||
* file name : asm_parser.h *
|
||||
* author : *
|
||||
* description : this header file declares the functions for those *
|
||||
* in the "asm_parser.c" library *
|
||||
* standard "string.h" C-library. *
|
||||
* *
|
||||
***************************************************************************
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASM_PARSER_H
|
||||
#define ASM_PARSER_H
|
||||
|
||||
@ -29,11 +18,26 @@ int parse_and(char *instr, char *instr_bin_str);
|
||||
int parse_or(char *instr, char *instr_bin_str);
|
||||
int parse_xor(char *instr, char *instr_bin_str);
|
||||
int parse_imm5(char *imm_str, int *imm_value);
|
||||
/* add additional helper functions to support other instructions */
|
||||
/* Add additional helper functions to support other instructions */
|
||||
int parse_nop(char *instr, char *instr_bin_str);
|
||||
int parse_not(char *instr, char *instr_bin_str);
|
||||
int parse_const(char *instr, char *instr_bin_str);
|
||||
int parse_imm9(char *imm_str, int *imm_value);
|
||||
int parse_sll(char *instr, char *instr_bin_str);
|
||||
int parse_sra(char *instr, char *instr_bin_str);
|
||||
int parse_srl(char *instr, char *instr_bin_str);
|
||||
int parse_uimm4(char *imm_str, int *imm_value);
|
||||
int parse_mod(char *instr, char *instr_bin_str);
|
||||
int parse_jmpr(char *instr, char *instr_bin_str);
|
||||
int parse_trap(char *instr, char *instr_bin_str);
|
||||
int parse_uimm8(char *imm_str, int *imm_value);
|
||||
int parse_rti(char *instr, char *instr_bin_str);
|
||||
|
||||
unsigned short int str_to_bin(char *instr_bin_str);
|
||||
int write_obj_file(char *filename, unsigned short int program_bin[ROWS], int instr_count);
|
||||
void int_to_bin_str(int num, int bits, char *bin_str);
|
||||
void to_uppercase(char *str);
|
||||
void trim(char *str);
|
||||
void write_uint16_big_endian(FILE *file, uint16_t value);
|
||||
|
||||
#endif
|
||||
|
||||
2
null
Normal file
2
null
Normal file
@ -0,0 +1,2 @@
|
||||
error: parse_instruction failed - too many commas
|
||||
Error on line 2: OR R4, , R5, R6
|
||||
@ -1 +1,7 @@
|
||||
ADD R1, R0 #5
|
||||
ADD R1, R0, R1
|
||||
MUL R2, R1, R1
|
||||
SUB R3, R2, R1
|
||||
DIV R1, R3, R2
|
||||
AND R1, R2, R3
|
||||
OR R1, R3, R2
|
||||
XOR R1, R3, R2
|
||||
3
test_case/invalid/case1.asm
Normal file
3
test_case/invalid/case1.asm
Normal file
@ -0,0 +1,3 @@
|
||||
ADD R1, R2, R3, R4
|
||||
SUB R5, R6
|
||||
MUL R7, R8, R9
|
||||
2
test_case/invalid/case2.asm
Normal file
2
test_case/invalid/case2.asm
Normal file
@ -0,0 +1,2 @@
|
||||
add R1, R2, R3
|
||||
DIV R4, R5, #10
|
||||
5
test_case/invalid/case3.asm
Normal file
5
test_case/invalid/case3.asm
Normal file
@ -0,0 +1,5 @@
|
||||
CMP R1, R2, R3
|
||||
CMPI R4, #15, #20
|
||||
CMPIU R5, 300
|
||||
CMPU R6, R7, R8
|
||||
MOD R9, R0, R1
|
||||
1
test_case/invalid/case4.asm
Normal file
1
test_case/invalid/case4.asm
Normal file
@ -0,0 +1 @@
|
||||
JSR 2048
|
||||
4
test_case/invalid/case5.asm
Normal file
4
test_case/invalid/case5.asm
Normal file
@ -0,0 +1,4 @@
|
||||
AND R1 R2 R3
|
||||
OR R4, , R5, R6
|
||||
XOR R7 R8, R9
|
||||
NOT R1 R2 R3
|
||||
3
test_case/valid/case1.asm
Normal file
3
test_case/valid/case1.asm
Normal file
@ -0,0 +1,3 @@
|
||||
ADD R1, R2, R3
|
||||
SUB R4, R5, R6
|
||||
MUL R0, R1, R2
|
||||
2
test_case/valid/case2.asm
Normal file
2
test_case/valid/case2.asm
Normal file
@ -0,0 +1,2 @@
|
||||
NOT R3, R4
|
||||
XOR R5, R6, R7
|
||||
7
test_case/valid/case3.asm
Normal file
7
test_case/valid/case3.asm
Normal file
@ -0,0 +1,7 @@
|
||||
ADD R1, R0, R1
|
||||
MUL R2, R1, R1
|
||||
SUB R3, R2, R1
|
||||
DIV R1, R3, R2
|
||||
AND R1, R2, R3
|
||||
OR R1, R3, R2
|
||||
XOR R1, R3, R2
|
||||
1
test_case/valid/case4.asm
Normal file
1
test_case/valid/case4.asm
Normal file
@ -0,0 +1 @@
|
||||
CONST R1 #123
|
||||
4
test_case/valid/case5.asm
Normal file
4
test_case/valid/case5.asm
Normal file
@ -0,0 +1,4 @@
|
||||
AND R1, R2, R3
|
||||
OR R4, R5, R6
|
||||
XOR R7, R0, R1
|
||||
AND R2, R3, R4
|
||||
Loading…
x
Reference in New Issue
Block a user