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
|
SRC_ASM_PARSER = asm_parser.c
|
||||||
OBJ_ASM_PARSER = asm_parser.o
|
OBJ_ASM_PARSER = asm_parser.o
|
||||||
TARGET = assembler
|
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)
|
all: $(TARGET)
|
||||||
|
|
||||||
assembler: $(OBJ_ASM_PARSER) $(SRC_ASSEMBLER)
|
assembler: $(OBJ_ASM_PARSER) $(SRC_ASSEMBLER)
|
||||||
@ -12,6 +20,31 @@ assembler: $(OBJ_ASM_PARSER) $(SRC_ASSEMBLER)
|
|||||||
asm_parser.o: $(SRC_ASM_PARSER)
|
asm_parser.o: $(SRC_ASM_PARSER)
|
||||||
$(CC) $(CFLAGS) -c $(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:
|
clean:
|
||||||
rm -f $(OBJ_ASM_PARSER)
|
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]);
|
free(tokens[i]);
|
||||||
}
|
}
|
||||||
return ret;
|
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 {
|
} else {
|
||||||
printf("error: parse_instruction failed\n");
|
printf("error: parse_instruction failed\n");
|
||||||
for (int i = 0; i < token_count; i++) {
|
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);
|
fclose(file);
|
||||||
return 0;
|
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
|
#ifndef ASM_PARSER_H
|
||||||
#define 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_or(char *instr, char *instr_bin_str);
|
||||||
int parse_xor(char *instr, char *instr_bin_str);
|
int parse_xor(char *instr, char *instr_bin_str);
|
||||||
int parse_imm5(char *imm_str, int *imm_value);
|
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);
|
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);
|
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 int_to_bin_str(int num, int bits, char *bin_str);
|
||||||
void to_uppercase(char *str);
|
void to_uppercase(char *str);
|
||||||
void trim(char *str);
|
void trim(char *str);
|
||||||
void write_uint16_big_endian(FILE *file, uint16_t value);
|
void write_uint16_big_endian(FILE *file, uint16_t value);
|
||||||
|
|
||||||
#endif
|
#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