extract assembling line
This commit is contained in:
parent
af0214739c
commit
0bdbaa7f1f
1
Makefile
1
Makefile
@ -8,7 +8,6 @@ C_FLAGS = \
|
||||
-Wall -Wextra -Wpedantic -Wconversion \
|
||||
-pedantic -pedantic-errors \
|
||||
-Wno-unused-variable \
|
||||
-Wno-unused-parameter \
|
||||
-I. \
|
||||
|
||||
L_FLAGS = -pthread
|
||||
|
308
asm/asm.c
308
asm/asm.c
@ -17,62 +17,26 @@ static inline void set_mov_addr_is_reg(uint32_t* ins);
|
||||
static inline void set_mov_is_store(uint32_t* ins);
|
||||
static inline uint16_t linety_arithm_ins(LineTy ty);
|
||||
|
||||
uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
|
||||
uint16_t assemble_line(uint16_t* out, const Line* line)
|
||||
{
|
||||
const bool debug = false;
|
||||
|
||||
uint16_t ip = 0;
|
||||
|
||||
typedef struct {
|
||||
int label;
|
||||
uint16_t ptr;
|
||||
} UnresolvedLabel;
|
||||
typedef struct {
|
||||
int label;
|
||||
uint16_t ip;
|
||||
} ResolvedLabel;
|
||||
|
||||
UnresolvedLabel* unres_labels = malloc(sizeof(UnresolvedLabel) * 64);
|
||||
size_t unres_labels_size = 0;
|
||||
|
||||
ResolvedLabel* res_labels = malloc(sizeof(ResolvedLabel) * 64);
|
||||
size_t res_labels_size = 0;
|
||||
|
||||
#define ADD_LABEL(LABEL) \
|
||||
{ \
|
||||
unres_labels[unres_labels_size++] = (UnresolvedLabel) { LABEL, ip }; \
|
||||
out[ip++] = 0; \
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
printf("assembling...\n");
|
||||
printf("ip op n data...\n");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < lines_size; ++i) {
|
||||
bool is_label = false;
|
||||
bool is_data = false;
|
||||
|
||||
const Line* line = &lines[i];
|
||||
uint16_t ins_ip = ip;
|
||||
switch (line->ty) {
|
||||
case LineTy_Label: {
|
||||
res_labels[res_labels_size++]
|
||||
= (ResolvedLabel) { line->op1.label, ip * 2 };
|
||||
|
||||
is_label = true;
|
||||
case LineTy_Label:
|
||||
case LineTy_DataLabel:
|
||||
case LineTy_Jmp_Label:
|
||||
case LineTy_Jnz_Label:
|
||||
case LineTy_Cmp_Label:
|
||||
case LineTy_Mov16_Reg_Label:
|
||||
case LineTy_Mov16_Reg_MemLabel:
|
||||
case LineTy_Mov16_MemLabel_Reg:
|
||||
case LineTy_Call_Label:
|
||||
case LineTy_Lit_Label: {
|
||||
fprintf(stderr, "error: labels not supported %d\n", line->ty);
|
||||
break;
|
||||
}
|
||||
case LineTy_DataImm: {
|
||||
out[ip++] = line->op1.imm;
|
||||
|
||||
is_data = true;
|
||||
break;
|
||||
}
|
||||
case LineTy_DataLabel: {
|
||||
ADD_LABEL(line->op1.label);
|
||||
|
||||
is_data = true;
|
||||
break;
|
||||
}
|
||||
case LineTy_Nop: {
|
||||
@ -100,15 +64,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
|
||||
out[ip++] = op1;
|
||||
break;
|
||||
}
|
||||
case LineTy_Jmp_Label: {
|
||||
int op1 = line->op1.label;
|
||||
|
||||
uint32_t ins = Op_Jmp;
|
||||
set_is_imm(&ins);
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(op1);
|
||||
break;
|
||||
}
|
||||
case LineTy_JmpFar_Reg_Reg: {
|
||||
uint16_t op1 = line->op1.reg;
|
||||
uint16_t op2 = line->op2.reg;
|
||||
@ -184,18 +139,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
|
||||
out[ip++] = op2;
|
||||
break;
|
||||
}
|
||||
case LineTy_Jnz_Label: {
|
||||
uint16_t op1 = line->op1.reg;
|
||||
int op2 = line->op2.label;
|
||||
|
||||
uint32_t ins = Op_Jnz;
|
||||
set_is_imm(&ins);
|
||||
add_op1_reg(&ins, op1);
|
||||
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(op2);
|
||||
break;
|
||||
}
|
||||
case LineTy_Cmp_Reg: {
|
||||
uint16_t op1 = line->op1.reg;
|
||||
uint16_t op2 = line->op2.reg;
|
||||
@ -219,18 +162,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
|
||||
out[ip++] = op2;
|
||||
break;
|
||||
}
|
||||
case LineTy_Cmp_Label: {
|
||||
uint16_t op1 = line->op1.reg;
|
||||
int op2 = line->op2.label;
|
||||
|
||||
uint32_t ins = Op_Cmp;
|
||||
set_is_imm(&ins);
|
||||
add_op1_reg(&ins, op1);
|
||||
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(op2);
|
||||
break;
|
||||
}
|
||||
case LineTy_Mov8_Reg_Reg: {
|
||||
uint16_t dst = line->dst.reg;
|
||||
uint16_t op2 = line->op2.reg;
|
||||
@ -362,18 +293,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
|
||||
out[ip++] = op2;
|
||||
break;
|
||||
}
|
||||
case LineTy_Mov16_Reg_Label: {
|
||||
uint16_t dst = line->dst.reg;
|
||||
int op2 = line->op2.label;
|
||||
|
||||
uint32_t ins = Op_Mov16;
|
||||
set_is_imm(&ins);
|
||||
ins |= (dst & 0xfu) << 12;
|
||||
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(op2);
|
||||
break;
|
||||
}
|
||||
case LineTy_Mov16_Reg_MemReg: {
|
||||
uint16_t dst = line->dst.reg;
|
||||
uint16_t op2 = line->op2.reg;
|
||||
@ -401,18 +320,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
|
||||
out[ip++] = op2;
|
||||
break;
|
||||
}
|
||||
case LineTy_Mov16_Reg_MemLabel: {
|
||||
uint16_t dst = line->dst.reg;
|
||||
|
||||
uint32_t ins = Op_Mov16;
|
||||
set_is_imm(&ins);
|
||||
set_mov_is_memory(&ins);
|
||||
add_dst_reg(&ins, dst);
|
||||
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(line->op2.label);
|
||||
break;
|
||||
}
|
||||
case LineTy_Mov16_MemReg_Reg: {
|
||||
uint16_t dst = line->dst.reg;
|
||||
uint16_t op2 = line->op2.reg;
|
||||
@ -471,19 +378,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
|
||||
out[ip++] = op2;
|
||||
break;
|
||||
}
|
||||
case LineTy_Mov16_MemLabel_Reg: {
|
||||
int dst = line->dst.label;
|
||||
uint16_t op2 = line->op2.reg;
|
||||
|
||||
uint32_t ins = Op_Mov16;
|
||||
add_op2_reg(&ins, op2);
|
||||
set_mov_is_memory(&ins);
|
||||
set_mov_is_store(&ins);
|
||||
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(dst);
|
||||
break;
|
||||
}
|
||||
case LineTy_In_Reg: {
|
||||
uint16_t dst = line->dst.reg;
|
||||
uint16_t op1 = line->op1.reg;
|
||||
@ -526,16 +420,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
|
||||
out[ip++] = op1;
|
||||
break;
|
||||
}
|
||||
case LineTy_Call_Label: {
|
||||
int op1 = line->op1.label;
|
||||
|
||||
uint32_t ins = Op_Call;
|
||||
set_is_imm(&ins);
|
||||
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(op1);
|
||||
break;
|
||||
}
|
||||
case LineTy_CallFar_Reg_Reg: {
|
||||
uint16_t op1 = line->op1.reg;
|
||||
uint16_t op2 = line->op2.reg;
|
||||
@ -618,16 +502,6 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
|
||||
out[ip++] = op1;
|
||||
break;
|
||||
}
|
||||
case LineTy_Lit_Label: {
|
||||
int op1 = line->op1.label;
|
||||
|
||||
uint32_t ins = Op_Lit;
|
||||
set_is_imm(&ins);
|
||||
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(op1);
|
||||
break;
|
||||
}
|
||||
case LineTy_Int: {
|
||||
uint16_t int_id = line->op1.imm & 0xff;
|
||||
|
||||
@ -704,6 +578,164 @@ uint16_t assemble_to_binary(uint16_t* out, const Line* lines, size_t lines_size)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
|
||||
uint16_t assemble_lines_with_labels(
|
||||
uint16_t* out, const Line* lines, size_t lines_size)
|
||||
{
|
||||
const bool debug = false;
|
||||
|
||||
uint16_t ip = 0;
|
||||
|
||||
typedef struct {
|
||||
int label;
|
||||
uint16_t ptr;
|
||||
} UnresolvedLabel;
|
||||
typedef struct {
|
||||
int label;
|
||||
uint16_t ip;
|
||||
} ResolvedLabel;
|
||||
|
||||
UnresolvedLabel* unres_labels = malloc(sizeof(UnresolvedLabel) * 64);
|
||||
size_t unres_labels_size = 0;
|
||||
|
||||
ResolvedLabel* res_labels = malloc(sizeof(ResolvedLabel) * 64);
|
||||
size_t res_labels_size = 0;
|
||||
|
||||
#define ADD_LABEL(LABEL) \
|
||||
{ \
|
||||
unres_labels[unres_labels_size++] = (UnresolvedLabel) { LABEL, ip }; \
|
||||
out[ip++] = 0; \
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
printf("assembling...\n");
|
||||
printf("ip op n data...\n");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < lines_size; ++i) {
|
||||
bool is_label = false;
|
||||
bool is_data = false;
|
||||
|
||||
const Line* line = &lines[i];
|
||||
uint16_t ins_ip = ip;
|
||||
switch (line->ty) {
|
||||
case LineTy_Label: {
|
||||
res_labels[res_labels_size++]
|
||||
= (ResolvedLabel) { line->op1.label, ip * 2 };
|
||||
|
||||
is_label = true;
|
||||
break;
|
||||
}
|
||||
case LineTy_DataImm: {
|
||||
ip += assemble_line(&out[ip], line);
|
||||
|
||||
is_data = true;
|
||||
break;
|
||||
}
|
||||
case LineTy_DataLabel: {
|
||||
ADD_LABEL(line->op1.label);
|
||||
|
||||
is_data = true;
|
||||
break;
|
||||
}
|
||||
case LineTy_Jmp_Label: {
|
||||
int op1 = line->op1.label;
|
||||
|
||||
uint32_t ins = Op_Jmp;
|
||||
set_is_imm(&ins);
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(op1);
|
||||
break;
|
||||
}
|
||||
case LineTy_Jnz_Label: {
|
||||
uint16_t op1 = line->op1.reg;
|
||||
int op2 = line->op2.label;
|
||||
|
||||
uint32_t ins = Op_Jnz;
|
||||
set_is_imm(&ins);
|
||||
add_op1_reg(&ins, op1);
|
||||
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(op2);
|
||||
break;
|
||||
}
|
||||
case LineTy_Cmp_Label: {
|
||||
uint16_t op1 = line->op1.reg;
|
||||
int op2 = line->op2.label;
|
||||
|
||||
uint32_t ins = Op_Cmp;
|
||||
set_is_imm(&ins);
|
||||
add_op1_reg(&ins, op1);
|
||||
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(op2);
|
||||
break;
|
||||
}
|
||||
case LineTy_Mov16_Reg_Label: {
|
||||
uint16_t dst = line->dst.reg;
|
||||
int op2 = line->op2.label;
|
||||
|
||||
uint32_t ins = Op_Mov16;
|
||||
set_is_imm(&ins);
|
||||
ins |= (dst & 0xfu) << 12;
|
||||
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(op2);
|
||||
break;
|
||||
}
|
||||
|
||||
case LineTy_Mov16_Reg_MemLabel: {
|
||||
uint16_t dst = line->dst.reg;
|
||||
|
||||
uint32_t ins = Op_Mov16;
|
||||
set_is_imm(&ins);
|
||||
set_mov_is_memory(&ins);
|
||||
add_dst_reg(&ins, dst);
|
||||
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(line->op2.label);
|
||||
break;
|
||||
}
|
||||
case LineTy_Mov16_MemLabel_Reg: {
|
||||
int dst = line->dst.label;
|
||||
uint16_t op2 = line->op2.reg;
|
||||
|
||||
uint32_t ins = Op_Mov16;
|
||||
add_op2_reg(&ins, op2);
|
||||
set_mov_is_memory(&ins);
|
||||
set_mov_is_store(&ins);
|
||||
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(dst);
|
||||
break;
|
||||
}
|
||||
case LineTy_Call_Label: {
|
||||
int op1 = line->op1.label;
|
||||
|
||||
uint32_t ins = Op_Call;
|
||||
set_is_imm(&ins);
|
||||
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(op1);
|
||||
break;
|
||||
}
|
||||
case LineTy_Lit_Label: {
|
||||
int op1 = line->op1.label;
|
||||
|
||||
uint32_t ins = Op_Lit;
|
||||
set_is_imm(&ins);
|
||||
|
||||
out[ip++] = (uint16_t)ins;
|
||||
ADD_LABEL(op1);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
ip += assemble_line(&out[ip], line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
if (!is_label) {
|
||||
|
@ -114,7 +114,7 @@ typedef struct {
|
||||
uint16_t offset;
|
||||
} Line;
|
||||
|
||||
uint16_t assemble_to_binary(
|
||||
uint16_t assemble_lines_with_labels(
|
||||
uint16_t* out, const Line* lines, size_t lines_size);
|
||||
|
||||
Line s_label(int label);
|
||||
|
@ -105,6 +105,7 @@ Line s_jnz_l(Reg op1_reg, int op2_label)
|
||||
{
|
||||
return (Line) {
|
||||
.ty = LineTy_Jnz_Label,
|
||||
.op1 = (Ex) { .reg = (uint16_t)op1_reg },
|
||||
.op2 = (Ex) { .label = op2_label },
|
||||
};
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
-pedantic
|
||||
-pedantic-errors
|
||||
-Wno-unused-variable
|
||||
-Wno-unused-parameter
|
||||
# -Wno-unused-parameter
|
||||
# -Wno-unused-function
|
||||
-I.
|
||||
|
||||
|
@ -203,7 +203,7 @@ void write_program(FILE* fp)
|
||||
|
||||
printf("assembling program...\n");
|
||||
uint16_t program_size
|
||||
= assemble_to_binary(program, program_asm, program_asm_size);
|
||||
= assemble_lines_with_labels(program, program_asm, program_asm_size);
|
||||
printf("done!\n");
|
||||
printf("program size = %d\n", program_size);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user