#ifndef WONKY_INTEL_ASM_INSTRUCTION_C
#define WONKY_INTEL_ASM_INSTRUCTION_C WONKY_INTEL_ASM_INSTRUCTION_C
#include <intel_instruction.h>
struct Intel_Asm_Instruction* get_intel_asm_import(char *what)
{
return get_intel_asm_label_inner(what,INTEL_ASM_OP_IMPORT);
}
struct Intel_Asm_Instruction* get_intel_asm_export(char *what)
{
return get_intel_asm_label_inner(what,INTEL_ASM_OP_EXPORT);
}
struct Intel_Asm_Instruction* get_intel_asm_label_inner(char *label,enum Intel_Asm_Instruction_Type type)
{
struct Intel_Asm_Label *ret;
ret=wonky_malloc(sizeof(struct Intel_Asm_Label));
ret->type=type;
ret->label_name=label;
return (struct Intel_Asm_Instruction*)ret;
}
struct Intel_Asm_Instruction* get_intel_asm_label(char *label)
{
return get_intel_asm_label_inner(label,INTEL_ASM_OP_LABEL);
}
struct Intel_Asm_Instruction* get_intel_asm_new_unique_label(struct Compile_Data_Intel_Asm *compile_data)
{
struct Intel_Asm_Label *ret;
char *label;
label=wonky_calloc(1,1024);
if(snprintf(label,1024,"_label_%d",compile_data->number_of_anon_labels)!=1024)
label[1023]='\0';/*TODO throw an error*/
++compile_data->number_of_anon_labels;
ret=wonky_malloc(sizeof(struct Intel_Asm_Label));
ret->type=INTEL_ASM_OP_LABEL;
ret->label_name=label;
return (struct Intel_Asm_Instruction*)ret;
}
struct Intel_Asm_Instruction* get_intel_asm_binary_instruction(struct Intel_Asm_Memory_Location *left,struct Intel_Asm_Memory_Location *right,enum Intel_Asm_Instruction_Type type)
{
struct Intel_Asm_Instruction_Binary *ret;
ret=wonky_malloc(sizeof(struct Intel_Asm_Instruction_Binary));
ret->type=type;
ret->left=left;
ret->right=right;
return (struct Intel_Asm_Instruction*)ret;
}
struct Intel_Asm_Instruction* get_intel_asm_unary_instruction(struct Intel_Asm_Memory_Location *operand,enum Intel_Asm_Instruction_Type type)
{
struct Intel_Asm_Instruction_Unary *ret;
ret=wonky_malloc(sizeof(struct Intel_Asm_Instruction_Unary));
ret->type=type;
ret->operand=operand;
return (struct Intel_Asm_Instruction*)ret;
}
struct Intel_Asm_Instruction* get_intel_asm_jump_instruction(struct Intel_Asm_Label *where_to,enum Intel_Asm_Instruction_Type type)
{
struct Intel_Asm_Instruction_Jump *ret;
ret=wonky_malloc(sizeof(struct Intel_Asm_Instruction_Jump));
ret->type=type;
ret->where_to=where_to;
return (struct Intel_Asm_Instruction*)ret;
}
struct Intel_Asm_Instruction* get_intel_asm_simple_instruction(enum Intel_Asm_Instruction_Type type)
{
struct Intel_Asm_Instruction *ret;
ret=wonky_malloc(sizeof(struct Intel_Asm_Instruction));
ret->type=type;
return ret;
}
struct Intel_Asm_Instruction* get_intel_asm_define_bytes(unsigned char *bytes,int number_of_bytes)
{
struct Intel_Asm_Instruction_Define_Bytes *ret;
int i;
ret=wonky_malloc(sizeof(struct Intel_Asm_Instruction_Define_Bytes));
ret->type=INTEL_ASM_OP_DEFINE_BYTES;
ret->number_of_bytes=number_of_bytes;
ret->bytes=wonky_malloc(number_of_bytes);
for(i=0;i<number_of_bytes;++i)
ret->bytes[i]=bytes[i];
return (struct Intel_Asm_Instruction*)ret;
}
struct Intel_Asm_Instruction* intel_asm_get_pop(enum Intel_Asm_Memory_Location_Type reg)
{
return get_intel_asm_unary_instruction(get_intel_asm_register(reg),INTEL_ASM_OP_POP);
}
struct Intel_Asm_Instruction* intel_asm_get_push(enum Intel_Asm_Memory_Location_Type reg)
{
return get_intel_asm_unary_instruction(get_intel_asm_register(reg),INTEL_ASM_OP_PUSH);
}
void save_intel_asm_instruction(struct Intel_Asm_Instruction *instruction,struct wonky_stream *out)
{
typedef void (*map_entry)(void *,struct wonky_stream *out);
static const map_entry map[INTEL_ASM_OP_END]
=
{
[INTEL_ASM_OP_ADD]=(map_entry)save_intel_asm_binary_instruction,
[INTEL_ASM_OP_SUB]=(map_entry)save_intel_asm_binary_instruction,
[INTEL_ASM_OP_MOV]=(map_entry)save_intel_asm_binary_instruction,
[INTEL_ASM_OP_MUL]=(map_entry)save_intel_asm_unary_instruction,
[INTEL_ASM_OP_DIV]=(map_entry)save_intel_asm_unary_instruction,
[INTEL_ASM_OP_JMP]=(map_entry)save_intel_asm_jump_instruction,
[INTEL_ASM_OP_TEST]=(map_entry)save_intel_asm_binary_instruction,
[INTEL_ASM_OP_CMP]=(map_entry)save_intel_asm_binary_instruction,
[INTEL_ASM_OP_SETL]=(map_entry)save_intel_asm_unary_instruction,
[INTEL_ASM_OP_SETE]=(map_entry)save_intel_asm_unary_instruction,
[INTEL_ASM_OP_SETNE]=(map_entry)save_intel_asm_unary_instruction,
[INTEL_ASM_OP_SETG]=(map_entry)save_intel_asm_unary_instruction,
[INTEL_ASM_OP_SETAE]=(map_entry)save_intel_asm_unary_instruction,
[INTEL_ASM_OP_SETBE]=(map_entry)save_intel_asm_unary_instruction,
[INTEL_ASM_OP_JE]=(map_entry)save_intel_asm_jump_instruction,
[INTEL_ASM_OP_JL]=(map_entry)save_intel_asm_jump_instruction,
[INTEL_ASM_OP_JNZ]=(map_entry)save_intel_asm_jump_instruction,
[INTEL_ASM_OP_JZ]=(map_entry)save_intel_asm_jump_instruction,
[INTEL_ASM_OP_RET]=(map_entry)save_intel_asm_simple_instruction,
[INTEL_ASM_OP_CALL]=(map_entry)save_intel_asm_unary_instruction,
[INTEL_ASM_OP_AND]=(map_entry)save_intel_asm_binary_instruction,
[INTEL_ASM_OP_XOR]=(map_entry)save_intel_asm_binary_instruction,
[INTEL_ASM_OP_OR]=(map_entry)save_intel_asm_binary_instruction,
[INTEL_ASM_OP_NOP]=(map_entry)save_intel_asm_simple_instruction,
[INTEL_ASM_OP_LABEL]=(map_entry)save_intel_asm_label,
[INTEL_ASM_OP_IMPORT]=(map_entry)save_intel_asm_import,
[INTEL_ASM_OP_EXPORT]=(map_entry)save_intel_asm_export,
[INTEL_ASM_OP_POP]=(map_entry)save_intel_asm_unary_instruction,
[INTEL_ASM_OP_SAL]=(map_entry)save_intel_asm_binary_instruction,
[INTEL_ASM_OP_SAR]=(map_entry)save_intel_asm_binary_instruction,
[INTEL_ASM_OP_PUSH]=(map_entry)save_intel_asm_unary_instruction,
[INTEL_ASM_OP_NEG]=(map_entry)save_intel_asm_unary_instruction,
[INTEL_ASM_OP_INC]=(map_entry)save_intel_asm_unary_instruction,
[INTEL_ASM_OP_DEC]=(map_entry)save_intel_asm_unary_instruction,
[INTEL_ASM_OP_NOT]=(map_entry)save_intel_asm_unary_instruction,
[INTEL_ASM_OP_DEFINE_BYTES]=(map_entry)save_intel_asm_define_bytes,
};
wonky_assert(map[instruction->type]!=NULL);
map[instruction->type](instruction,out);
}
void save_intel_asm_label(struct Intel_Asm_Label *label,struct wonky_stream *out)
{
wonky_fprintf(out,"%s:\n",label->label_name);
}
void save_intel_asm_import(struct Intel_Asm_Label *im,struct wonky_stream *out)
{
wonky_fprintf(out,"extern %s\n",im->label_name);
}
void save_intel_asm_export(struct Intel_Asm_Label *ex,struct wonky_stream *out)
{
wonky_fprintf(out,"global %s\n",ex->label_name);
}
void save_intel_asm_binary_instruction(struct Intel_Asm_Instruction_Binary *bin,struct wonky_stream *out)
{
const char *map[INTEL_ASM_OP_END]
=
{
[INTEL_ASM_OP_ADD]="ADD",
[INTEL_ASM_OP_SUB]="SUB",
[INTEL_ASM_OP_MOV]="MOV",
[INTEL_ASM_OP_TEST]="TEST",
[INTEL_ASM_OP_AND]="AND",
[INTEL_ASM_OP_XOR]="XOR",
[INTEL_ASM_OP_OR]="OR",
[INTEL_ASM_OP_CMP]="CMP",
[INTEL_ASM_OP_SAL]="SAL",
[INTEL_ASM_OP_SAR]="SAR",
};
wonky_assert(map[bin->type]!=NULL);
wonky_fprintf(out,"%s ",map[bin->type]);
save_intel_asm_location(bin->left,out);
wonky_fprintf(out,", ");
save_intel_asm_location(bin->right,out);
wonky_fprintf(out,"\n");
}
void save_intel_asm_unary_instruction(struct Intel_Asm_Instruction_Unary *unary,struct wonky_stream *out)
{
const char *map[INTEL_ASM_OP_END]
=
{
[INTEL_ASM_OP_POP]="POP",
[INTEL_ASM_OP_PUSH]="PUSH",
[INTEL_ASM_OP_CALL]="CALL",
[INTEL_ASM_OP_MUL]="MUL",
[INTEL_ASM_OP_DIV]="DIV",
[INTEL_ASM_OP_SETL]="SETL",
[INTEL_ASM_OP_SETE]="SETE",
[INTEL_ASM_OP_SETNE]="SETNE",
[INTEL_ASM_OP_SETG]="SETG",
[INTEL_ASM_OP_SETAE]="SETAE",
[INTEL_ASM_OP_SETBE]="SETBE",
[INTEL_ASM_OP_NEG]="NEG",
[INTEL_ASM_OP_INC]="INC",
[INTEL_ASM_OP_DEC]="DEC",
[INTEL_ASM_OP_NOT]="NOT",
};
wonky_assert(map[unary->type]!=NULL);
wonky_fprintf(out,"%s ",map[unary->type]);
save_intel_asm_location(unary->operand,out);
wonky_fprintf(out,"\n");
}
void save_intel_asm_jump_instruction(struct Intel_Asm_Instruction_Jump *jmp,struct wonky_stream *out)
{
const char *map[INTEL_ASM_OP_END]
=
{
[INTEL_ASM_OP_JMP]="JMP",
[INTEL_ASM_OP_JE]="JE",
[INTEL_ASM_OP_JL]="JL",
[INTEL_ASM_OP_JNZ]="JNZ",
[INTEL_ASM_OP_JZ]="JZ",
};
wonky_assert(map[jmp->type]!=NULL);
wonky_fprintf(out,"%s %s",map[jmp->type],jmp->where_to->label_name);
wonky_fprintf(out,"\n");
}
void save_intel_asm_simple_instruction(struct Intel_Asm_Instruction *instruction,struct wonky_stream *out)
{
static const char *map[INTEL_ASM_OP_END]
=
{
[INTEL_ASM_OP_RET]="RET",
[INTEL_ASM_OP_NOP]="NOP",
};
wonky_assert(map[instruction->type]!=NULL);
wonky_fprintf(out,"%s\n",map[instruction->type]);
}
void save_intel_asm_define_bytes(struct Intel_Asm_Instruction_Define_Bytes *instruction,struct wonky_stream *out)
{
int i;
wonky_fprintf(out,"db ");
for(i=0;i<instruction->number_of_bytes;++i)
{
wonky_fprintf(out,"0x%x",instruction->bytes[i]);
if(i<instruction->number_of_bytes-1)
wonky_fprintf(out,", ");
}
wonky_fprintf(out,"\n");
}
#endif