extract assembling line

This commit is contained in:
sfja 2025-04-01 17:15:37 +02:00
parent af0214739c
commit 0bdbaa7f1f
7 changed files with 574 additions and 541 deletions

View File

@ -8,7 +8,6 @@ C_FLAGS = \
-Wall -Wextra -Wpedantic -Wconversion \ -Wall -Wextra -Wpedantic -Wconversion \
-pedantic -pedantic-errors \ -pedantic -pedantic-errors \
-Wno-unused-variable \ -Wno-unused-variable \
-Wno-unused-parameter \
-I. \ -I. \
L_FLAGS = -pthread L_FLAGS = -pthread

308
asm/asm.c
View File

@ -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 void set_mov_is_store(uint32_t* ins);
static inline uint16_t linety_arithm_ins(LineTy ty); 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; 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) { switch (line->ty) {
case LineTy_Label: { case LineTy_Label:
res_labels[res_labels_size++] case LineTy_DataLabel:
= (ResolvedLabel) { line->op1.label, ip * 2 }; case LineTy_Jmp_Label:
case LineTy_Jnz_Label:
is_label = true; 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; break;
} }
case LineTy_DataImm: { case LineTy_DataImm: {
out[ip++] = line->op1.imm; out[ip++] = line->op1.imm;
is_data = true;
break;
}
case LineTy_DataLabel: {
ADD_LABEL(line->op1.label);
is_data = true;
break; break;
} }
case LineTy_Nop: { 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; out[ip++] = op1;
break; 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: { case LineTy_JmpFar_Reg_Reg: {
uint16_t op1 = line->op1.reg; uint16_t op1 = line->op1.reg;
uint16_t op2 = line->op2.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; out[ip++] = op2;
break; 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: { case LineTy_Cmp_Reg: {
uint16_t op1 = line->op1.reg; uint16_t op1 = line->op1.reg;
uint16_t op2 = line->op2.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; out[ip++] = op2;
break; 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: { case LineTy_Mov8_Reg_Reg: {
uint16_t dst = line->dst.reg; uint16_t dst = line->dst.reg;
uint16_t op2 = line->op2.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; out[ip++] = op2;
break; 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: { case LineTy_Mov16_Reg_MemReg: {
uint16_t dst = line->dst.reg; uint16_t dst = line->dst.reg;
uint16_t op2 = line->op2.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; out[ip++] = op2;
break; 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: { case LineTy_Mov16_MemReg_Reg: {
uint16_t dst = line->dst.reg; uint16_t dst = line->dst.reg;
uint16_t op2 = line->op2.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; out[ip++] = op2;
break; 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: { case LineTy_In_Reg: {
uint16_t dst = line->dst.reg; uint16_t dst = line->dst.reg;
uint16_t op1 = line->op1.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; out[ip++] = op1;
break; 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: { case LineTy_CallFar_Reg_Reg: {
uint16_t op1 = line->op1.reg; uint16_t op1 = line->op1.reg;
uint16_t op2 = line->op2.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; out[ip++] = op1;
break; 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: { case LineTy_Int: {
uint16_t int_id = line->op1.imm & 0xff; 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; 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 (debug) {
if (!is_label) { if (!is_label) {

View File

@ -114,7 +114,7 @@ typedef struct {
uint16_t offset; uint16_t offset;
} Line; } Line;
uint16_t assemble_to_binary( uint16_t assemble_lines_with_labels(
uint16_t* out, const Line* lines, size_t lines_size); uint16_t* out, const Line* lines, size_t lines_size);
Line s_label(int label); Line s_label(int label);

View File

@ -105,6 +105,7 @@ Line s_jnz_l(Reg op1_reg, int op2_label)
{ {
return (Line) { return (Line) {
.ty = LineTy_Jnz_Label, .ty = LineTy_Jnz_Label,
.op1 = (Ex) { .reg = (uint16_t)op1_reg },
.op2 = (Ex) { .label = op2_label }, .op2 = (Ex) { .label = op2_label },
}; };
} }

View File

@ -7,7 +7,7 @@
-pedantic -pedantic
-pedantic-errors -pedantic-errors
-Wno-unused-variable -Wno-unused-variable
-Wno-unused-parameter # -Wno-unused-parameter
# -Wno-unused-function # -Wno-unused-function
-I. -I.

View File

@ -203,7 +203,7 @@ void write_program(FILE* fp)
printf("assembling program...\n"); printf("assembling program...\n");
uint16_t program_size 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("done!\n");
printf("program size = %d\n", program_size); printf("program size = %d\n", program_size);

View File

@ -1,5 +1,6 @@
#include "vm.h" #include "vm.h"
#include "common/arch.h" #include "common/arch.h"
#include "common/op_str.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>