#include "assembly.h" #include #include #include // Max instruction width is 25 characters without the null char // // INSTRUCTIONS: // BYTE 3 BYTE 2 BYTE 1 BYTE 0 // +===================================================+ // | | | | | // +===================================================+ // // // // INSTRUCTION FORMAT 0: // +===================================================+ // | OPCODE | 24 BIT IMMEDIATE ADDRESS | // +===================================================+ // // INSTRUCTION FORMAT 1: // +===================================================+ // | OPCODE | SOURCE REG | DEST REG | // +===================================================+ // // INSTRUCTION FORMAT 2: // +===================================================+ // | OPCODE | DEST REG | 16 BIT IMMEDIATE | // +===================================================+ // // // // OPCODE FORMAT: // ______________________________________________________________________________________________________ // |BIT | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | // +----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ // | | INSTR. FORMAT | 8bit opcode num : 16bit opcode num | // +----+-----------------+-----------------------------+-----------------------------------------------+ // // // INSTRUCTION FORMAT 0 OPCODE NUM: // +-------+----------------------------------+--------------+ // | NUM | DESCRIPTION | AFFECT FLAGS | // +-------+----------------------------------+--------------+ // | 5'd0 | NOP | NO | // +-------+----------------------------------+--------------+ // | 5'd1 | Unconditional Jump | NO | // +-------+----------------------------------+--------------+ // | 5'd2 | Jump if zero flag is set | NO | // +-------+----------------------------------+--------------+ // | 5'd3 | Jump if zero flag is not set | NO | // +-------+----------------------------------+--------------+ // | 5'd4 | Jump if carry flag is set | NO | // +-------+----------------------------------+--------------+ // | 5'd5 | Jump if carry flag is not set | NO | // // // INSTRUCTION FORMAT 1 OPCODE NUM: // +-------+----------------------------------+--------------+ // | NUM | DESCRIPTION | AFFECT FLAGS | // +-------+----------------------------------+--------------+ // | 13'd0 | ADD | YES | // +-------+----------------------------------+--------------| // | 13'd1 | SUBTRACT | YES | // +-------+----------------------------------+--------------| // | 13'd2 | SHIFT LEFT | YES | // +-------+----------------------------------+--------------| // | 13'd3 | SHIFT RIGHT | YES | // +-------+----------------------------------+--------------| // | 13'd4 | COMPARE (SUBTRACT WITHOUT SAVE) | YES | // // // INSTRUCTION FORMAT 2 OPCODE NUM: // +-------+----------------------------------------------+--------------+ // | NUM | DESCRIPTION | AFFECT FLAGS | // +-------+----------------------------------------------+--------------+ // | 5'd0 | MOV IMMEDIATE TO DEST LOW PART OF REGISTER | NO | // +-------+----------------------------------------------+--------------+ // | 5'd1 | MOV IMMEDIATE TO DEST HIGH PART OF REGISTER | NO | #define MAX_INSTRUCTION_LENGTH 26 char *disassemble(uint32_t opcode_be){ uint32_t opcode=(opcode_be&0x000000FF)<<24|(opcode_be&0x0000FF00)<<8|(opcode_be&0x00FF0000)>>8|(opcode_be&0xFF000000)>>24; char *ret=malloc(MAX_INSTRUCTION_LENGTH); if (!ret) return NULL; //////// PARSE BITECODE ////////// int instruction_format,opcode_num; uint32_t val; uint8_t val1; uint8_t val2; instruction_format=(opcode&0xE0000000)>>29; if(instruction_format==0){ // 8bit opcode opcode_num=(opcode&0x1F000000)>>24; val=opcode&0x00FFFFFF; switch(opcode_num){ case 0x00: snprintf(ret,MAX_INSTRUCTION_LENGTH,"NOP"); break; case 0x01: snprintf(ret,MAX_INSTRUCTION_LENGTH,"JMP $%06X",val); break; case 0x02: case 0x03: snprintf(ret,MAX_INSTRUCTION_LENGTH,"JMP %s,$%06X",opcode_num&1?"Z":"NZ",val); break; case 0x04: case 0x05: snprintf(ret,MAX_INSTRUCTION_LENGTH,"JMP %s,$%06X",opcode_num&1?"C":"NC",val); break; default: snprintf(ret,MAX_INSTRUCTION_LENGTH,"UNRECOGNISED INSTR"); break; } }else if(instruction_format==1){ // 16bit opcode opcode_num=(opcode&0x1FFF0000)>>16; val1=(opcode&0x0000FF00)>>8; val2=opcode&0x000000FF; switch(opcode_num){ case 0x00: snprintf(ret,MAX_INSTRUCTION_LENGTH,"ADD %%R%0d, %%R%0d",val1,val2); break; case 0x01: snprintf(ret,MAX_INSTRUCTION_LENGTH,"SUB %%R%0d, %%R%0d",val1,val2); break; case 0x02: snprintf(ret,MAX_INSTRUCTION_LENGTH,"SL %%R%0d",val1); break; case 0x03: snprintf(ret,MAX_INSTRUCTION_LENGTH,"SR %%R%0d",val1); break; case 0x04: snprintf(ret,MAX_INSTRUCTION_LENGTH,"CMP %%R%0d, %%R%0d",val1,val2); break; default: snprintf(ret,MAX_INSTRUCTION_LENGTH,"UNRECOGNISED INSTRUCTION"); break; } }else if(instruction_format==2){ // 16bit opcode opcode_num=(opcode&0x1FFF0000)>>16; val1=(opcode&0x00FF0000)>>16; val=opcode&0x0000FFFF; switch(opcode_num){ case 0x00: snprintf(ret,MAX_INSTRUCTION_LENGTH,"MOV $%04X, %%R%0dl",val,val1); break; case 0x01: snprintf(ret,MAX_INSTRUCTION_LENGTH,"MOV $%04X, %%R%0dh",val,val1); break; default: snprintf(ret,MAX_INSTRUCTION_LENGTH,"UNRECOGNISED INSTRUCTION"); break; } }else snprintf(ret,MAX_INSTRUCTION_LENGTH,"UNRECOGNISED INSTRUCTION"); return ret; }