lc4_asm_disassembling/submit/lc4_disassembler.c

131 lines
4.3 KiB
C
Raw Normal View History

2024-11-13 09:37:18 +08:00
/************************************************************************/
/* File Name : lc4_disassembler.c */
/* Purpose : This file implements the reverse assembler */
/* for LC4 assembly. It will be called by main() */
/* */
/* Author(s) : tjf and you */
/************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
2024-11-13 09:37:18 +08:00
#include "lc4_memory.h"
int reverse_assemble(row_of_memory *memory) {
row_of_memory *current = memory;
while (current != NULL) {
if (current->assembly == NULL) {
unsigned short instr = current->contents;
unsigned short opcode = (instr >> 12) & 0xF;
char *assembly = (char *)malloc(50);
if (assembly == NULL) {
return -1;
}
switch (opcode) {
case 0x0: // NOP or BR
if (instr == 0x0000) {
2024-11-13 10:34:48 +08:00
// sprintf(assembly, "NOP");
// here we remove nop instruct
assembly = NULL;
} else {
unsigned short n = (instr >> 11) & 0x1;
unsigned short z = (instr >> 10) & 0x1;
unsigned short p = (instr >> 9) & 0x1;
short offset = instr & 0x1FF;
if (offset & 0x100) {
offset |= 0xFE00;
}
char condition[4] = "";
if (n) strcat(condition, "n");
if (z) strcat(condition, "z");
if (p) strcat(condition, "p");
if (condition[0] == '\0') {
2024-11-13 10:34:48 +08:00
// sprintf(assembly, "NOP");
assembly = NULL;
} else {
sprintf(assembly, "BR%s #%d", condition, offset);
}
}
break;
case 0x1: { // Arithmetic operations
unsigned short sub_opcode = (instr >> 3) & 0x7;
unsigned short Rd = (instr >> 9) & 0x7;
unsigned short Rs = (instr >> 6) & 0x7;
if (((instr >> 5) & 0x1) == 0) {
unsigned short Rt = instr & 0x7;
switch (sub_opcode) {
case 0x0:
sprintf(assembly, "ADD R%d, R%d, R%d", Rd, Rs, Rt);
break;
case 0x1:
sprintf(assembly, "MUL R%d, R%d, R%d", Rd, Rs, Rt);
break;
case 0x2:
sprintf(assembly, "SUB R%d, R%d, R%d", Rd, Rs, Rt);
break;
case 0x3:
sprintf(assembly, "DIV R%d, R%d, R%d", Rd, Rs, Rt);
break;
default:
sprintf(assembly, "INVALID");
break;
}
} else {
short imm5 = instr & 0x1F;
if (imm5 & 0x10) {
imm5 |= 0xFFE0;
}
sprintf(assembly, "ADD R%d, R%d, #%d", Rd, Rs, imm5);
}
break;
}
case 0x5: { // Logical operations
unsigned short sub_opcode = (instr >> 3) & 0x7;
unsigned short Rd = (instr >> 9) & 0x7;
unsigned short Rs = (instr >> 6) & 0x7;
if (((instr >> 5) & 0x1) == 0) {
unsigned short Rt = instr & 0x7;
switch (sub_opcode) {
case 0x0:
sprintf(assembly, "AND R%d, R%d, R%d", Rd, Rs, Rt);
break;
case 0x1:
sprintf(assembly, "NOT R%d, R%d", Rd, Rs);
break;
case 0x2:
sprintf(assembly, "OR R%d, R%d, R%d", Rd, Rs, Rt);
break;
case 0x3:
sprintf(assembly, "XOR R%d, R%d, R%d", Rd, Rs, Rt);
break;
default:
sprintf(assembly, "INVALID");
break;
}
} else {
short imm5 = instr & 0x1F;
if (imm5 & 0x10) {
imm5 |= 0xFFE0;
}
sprintf(assembly, "AND R%d, R%d, #%d", Rd, Rs, imm5);
}
break;
}
case 0xF: { // TRAP
unsigned short trapvect8 = instr & 0xFF;
sprintf(assembly, "TRAP x%02X", trapvect8);
break;
}
/* Handle other opcodes similarly */
default:
// sprintf(assembly, "UNIMPLEMENTED");
assembly = NULL;
break;
}
current->assembly = assembly;
}
current = current->next;
}
return 0;
2024-11-13 09:37:18 +08:00
}