Fiddle around with chibicc

main
Justine Tunney 2020-12-19 13:39:09 -08:00
parent 921f63da68
commit 14d0292732
2 changed files with 269 additions and 136 deletions

View File

@ -252,6 +252,10 @@ static const char *g_input_path;
static const char *g_output_path;
static struct Strings g_include_paths;
static void PrintSlice(struct Slice s) {
fprintf(stderr, "%.*s\n", s.n, s.p);
}
static void AppendString(struct Strings *l, const char *p) {
l->p = realloc(l->p, ++l->n * sizeof(*l->p));
l->p[l->n - 1] = p;
@ -434,17 +438,20 @@ static void Tokenize(struct Assembler *a, char *path) {
line = 1;
bol = true;
while ((c = *p)) {
if (c == '#' || (c == '/' && bol)) {
p = strchr(p, '\n') + 1;
if (c == '#' || (c == '/' && bol) || (c == '/' && p[1] == '/')) {
p = strchr(p, '\n');
continue;
}
if (c == '\n') {
APPEND(a->things);
a->things.p[a->things.n - 1].t = TT_PUNCT;
a->things.p[a->things.n - 1].s = AppendLine(a, path, line);
a->things.p[a->things.n - 1].i = ';';
++p;
bol = true;
++line;
continue;
}
if (c == '\n') {
c = ';';
bol = true;
++line;
} else {
bol = false;
if (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f' ||
c == '\v' || c == ',') {
@ -456,7 +463,7 @@ static void Tokenize(struct Assembler *a, char *path) {
for (i = 1;; ++i) {
if (!(('a' <= p[i] && p[i] <= 'z') || ('A' <= p[i] && p[i] <= 'Z') ||
('0' <= p[i] && p[i] <= '9') || p[i] == '.' || p[i] == '_' ||
p[i] == '$' || p[i] == '(' || p[i] == ')')) {
p[i] == '$')) {
break;
}
}
@ -494,8 +501,7 @@ static void Tokenize(struct Assembler *a, char *path) {
for (i = 1;; ++i) {
if (('0' <= p[i] && p[i] <= '9') || p[i] == '-' || p[i] == '+') {
continue;
} else if (p[i] == '.' || p[i] == 'e' || p[i] == 'E' ||
p[i] == 'e') {
} else if (p[i] == '.' || p[i] == 'e' || p[i] == 'E' || p[i] == 'e') {
isfloat = true;
continue;
}
@ -579,7 +585,7 @@ static void Tokenize(struct Assembler *a, char *path) {
}
continue;
}
}
APPEND(a->things);
a->things.p[a->things.n - 1].t = TT_PUNCT;
a->things.p[a->things.n - 1].s = AppendLine(a, path, line);
@ -617,7 +623,7 @@ static wontreturn void Fail(struct Assembler *a, const char *fmt, ...) {
vfprintf(stderr, fmt, va);
va_end(va);
fputc('\n', stderr);
exit(1);
__die();
}
static void Label(struct Assembler *a, int name) {
@ -1161,6 +1167,13 @@ static wontreturn void InvalidRegister(struct Assembler *a) {
Fail(a, "invalid register");
}
static int GetRegisterReg(struct Assembler *a) {
int reg;
struct Slice wut;
if ((reg = FindRegReg(GetString(a))) == -1) InvalidRegister(a);
return reg;
}
static int GetRegisterRm(struct Assembler *a) {
int reg;
struct Slice wut;
@ -1215,6 +1228,7 @@ static int ParseMemory(struct Assembler *a, long *disp) {
}
static void EncodeModrm(struct Assembler *a, int reg, int mem, long disp) {
reg &= 7;
reg <<= 3;
if (mem & (HASBASE | HASINDEX)) {
if (mem & ISRIP) {
@ -1231,12 +1245,12 @@ static void EncodeModrm(struct Assembler *a, int reg, int mem, long disp) {
}
static void OnMov(struct Assembler *a, struct Slice op) {
int reg, mem;
long imm, disp;
int reg, rm, mem, modrm;
if (IsPunct(a, a->i, '$')) {
++a->i;
imm = GetInt(a);
if (IsSlice(a, a->i)) {
if (IsSlice(a, a->i)) { // imm -> reg
reg = GetRegisterRm(a);
if (reg & 0xff00) {
Emit(a, reg >> 8);
@ -1262,7 +1276,7 @@ static void OnMov(struct Assembler *a, struct Slice op) {
default:
Fail(a, "todo movd/movq");
}
} else {
} else { // imm -> mem
mem = ParseMemory(a, &disp);
if (mem & 0xff00) {
Emit(a, mem >> 8);
@ -1293,6 +1307,91 @@ static void OnMov(struct Assembler *a, struct Slice op) {
unreachable;
}
}
} else if (IsSlice(a, a->i)) {
reg = GetRegisterReg(a);
if (IsSlice(a, a->i)) { // reg -> reg
rm = GetRegisterRm(a);
if (((reg & 070) >> 3) != ((rm & 070) >> 3)) {
Fail(a, "size mismatch");
}
if ((reg | rm) & 0xff00) {
Emit(a, (reg | rm) >> 8);
}
modrm = 0300 | (reg & 7) << 3 | rm & 7;
switch ((reg & 070) >> 3) {
case 0:
Emit(a, 0x88);
Emit(a, modrm);
break;
case 1:
Emit(a, OSZ);
Emit(a, 0x89);
Emit(a, modrm);
break;
case 2:
case 3:
Emit(a, 0x89);
Emit(a, modrm);
break;
case 4:
Emit(a, 0x66);
Emit(a, 0x0F);
Emit(a, 0x6F);
Emit(a, modrm);
break;
default:
unreachable;
}
} else { // reg -> mem
mem = ParseMemory(a, &disp);
if ((reg | mem) & 0xff00) {
Emit(a, (reg | mem) >> 8);
}
modrm = 0300 | (reg & 7) << 3 | rm & 7;
switch ((reg & 070) >> 3) {
case 0:
Emit(a, 0x88);
EncodeModrm(a, reg, mem, 0);
break;
case 1:
Emit(a, OSZ);
Emit(a, 0x89);
EncodeModrm(a, reg, mem, 0);
break;
case 2:
case 3:
Emit(a, 0x89);
EncodeModrm(a, reg, mem, 0);
break;
default:
Fail(a, "todo movdqu");
}
}
} else { // mem -> reg
mem = ParseMemory(a, &disp);
reg = GetRegisterReg(a);
if ((reg | mem) & 0xff00) {
Emit(a, (reg | mem) >> 8);
}
modrm = 0300 | (reg & 7) << 3 | rm & 7;
switch ((reg & 070) >> 3) {
case 0:
Emit(a, 0x8A);
EncodeModrm(a, reg, mem, 0);
break;
case 1:
Emit(a, OSZ);
Emit(a, 0x8B);
EncodeModrm(a, reg, mem, 0);
break;
case 2:
case 3:
Emit(a, 0x8B);
EncodeModrm(a, reg, mem, 0);
break;
default:
Fail(a, "todo movdqu");
}
}
}

34
third_party/chibicc/hog.s vendored 100644
View File

@ -0,0 +1,34 @@
.globl _start
_start: rep movsb
/ add $333333,%rcx
/ test %eax,(%rcx) # 85 0001
push %r15
pop %r15
mov %al,%bl
mov %eax,%ecx # 89 0301
mov %ecx,%eax # 89 0310
mov %ecx,(%rbx)
mov (%rbx),%ecx
mov %xmm0,%xmm1
movb $1,(%rax)
movl $1,(%rax)
movl $1,0xffffff(%rax,%rbx,8)
mov $1,%bl
mov $123,%r8d
/ mov %ebx,%r8d
/ mov (%r8),%ebx
/ mov %ebx,(%r8)
/ movd %eax,%xmm0
/ movdqa %xmm0,%xmm8
/ movdqa %xmm8,%xmm1
/ paddw %xmm8,%xmm1
/ paddw %xmm1,%xmm8
hlt
ret $1
a: .asciz "ho","ggg"
.align 8
.section .text.yo
.zero 1
.byte 1
.hidden doge