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>
|
2024-11-13 10:19:53 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
2024-11-13 09:37:18 +08:00
|
|
|
#include "lc4_memory.h"
|
|
|
|
|
|
2024-11-13 10:19:53 +08:00
|
|
|
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) {
|
|
|
|
|
sprintf(assembly, "NOP");
|
|
|
|
|
} 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') {
|
|
|
|
|
sprintf(assembly, "NOP");
|
|
|
|
|
} 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
|
|
|
}
|