-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #55 from the-grue/nasm
Nasm code generator
- Loading branch information
Showing
239 changed files
with
38,506 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
#include "defs.h" | ||
#include "data.h" | ||
#include "decl.h" | ||
|
||
// Code generator for x86-64 | ||
// Copyright (c) 2019 Warren Toomey, GPL3 | ||
|
||
|
||
// List of available registers | ||
// and their names | ||
static int freereg[4]; | ||
static char *reglist[4]= { "r8", "r9", "r10", "r11" }; | ||
|
||
// Set all registers as available | ||
void freeall_registers(void) | ||
{ | ||
freereg[0]= freereg[1]= freereg[2]= freereg[3]= 1; | ||
} | ||
|
||
// Allocate a free register. Return the number of | ||
// the register. Die if no available registers. | ||
static int alloc_register(void) | ||
{ | ||
for (int i=0; i<4; i++) { | ||
if (freereg[i]) { | ||
freereg[i]= 0; | ||
return(i); | ||
} | ||
} | ||
fprintf(stderr, "Out of registers!\n"); | ||
exit(1); | ||
} | ||
|
||
// Return a register to the list of available registers. | ||
// Check to see if it's not already there. | ||
static void free_register(int reg) | ||
{ | ||
if (freereg[reg] != 0) { | ||
fprintf(stderr, "Error trying to free register %d\n", reg); | ||
exit(1); | ||
} | ||
freereg[reg]= 1; | ||
} | ||
|
||
// Print out the assembly preamble | ||
void cgpreamble() | ||
{ | ||
freeall_registers(); | ||
fputs( | ||
"\tglobal\tmain\n" | ||
"\textern\tprintf\n" | ||
"\tsection\t.text\n" | ||
"LC0:\tdb\t\"%d\",10,0\n" | ||
"printint:\n" | ||
"\tpush\trbp\n" | ||
"\tmov\trbp, rsp\n" | ||
"\tsub\trsp, 16\n" | ||
"\tmov\t[rbp-4], edi\n" | ||
"\tmov\teax, [rbp-4]\n" | ||
"\tmov\tesi, eax\n" | ||
"\tlea rdi, [rel LC0]\n" | ||
"\tmov eax, 0\n" | ||
"\tcall printf\n" | ||
"\tnop\n" | ||
"\tleave\n" | ||
"\tret\n" | ||
"\n" | ||
"main:\n" | ||
"\tpush\trbp\n" | ||
"\tmov rbp, rsp\n", | ||
Outfile); | ||
} | ||
|
||
// Print out the assembly postamble | ||
void cgpostamble() | ||
{ | ||
fputs( | ||
"\tmov eax, 0\n" | ||
"\tpop rbp\n" | ||
"\tret\n", | ||
Outfile); | ||
} | ||
|
||
// Load an integer literal value into a register. | ||
// Return the number of the register | ||
int cgload(int value) { | ||
|
||
// Get a new register | ||
int r= alloc_register(); | ||
|
||
// Print out the code to initialise it | ||
fprintf(Outfile, "\tmov\t%s, %d\n", reglist[r], value); | ||
return(r); | ||
} | ||
|
||
// Add two registers together and return | ||
// the number of the register with the result | ||
int cgadd(int r1, int r2) { | ||
fprintf(Outfile, "\tadd\t%s, %s\n", reglist[r2], reglist[r1]); | ||
free_register(r1); | ||
return(r2); | ||
} | ||
|
||
// Subtract the second register from the first and | ||
// return the number of the register with the result | ||
int cgsub(int r1, int r2) { | ||
fprintf(Outfile, "\tsub\t%s, %s\n", reglist[r1], reglist[r2]); | ||
free_register(r2); | ||
return(r1); | ||
} | ||
|
||
// Multiply two registers together and return | ||
// the number of the register with the result | ||
int cgmul(int r1, int r2) { | ||
fprintf(Outfile, "\timul\t%s, %s\n", reglist[r2], reglist[r1]); | ||
free_register(r1); | ||
return(r2); | ||
} | ||
|
||
// Divide the first register by the second and | ||
// return the number of the register with the result | ||
int cgdiv(int r1, int r2) { | ||
fprintf(Outfile, "\tmov\trax, %s\n", reglist[r1]); | ||
fprintf(Outfile, "\tcqo\n"); | ||
fprintf(Outfile, "\tidiv\t%s\n", reglist[r2]); | ||
fprintf(Outfile, "\tmov\t%s, rax\n", reglist[r1]); | ||
free_register(r2); | ||
return(r1); | ||
} | ||
|
||
// Call printint() with the given register | ||
void cgprintint(int r) { | ||
fprintf(Outfile, "\tmov\trdi, %s\n", reglist[r]); | ||
fprintf(Outfile, "\tcall\tprintint\n"); | ||
free_register(r); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,19 @@ | ||
comp1: cg.c expr.c gen.c main.c misc.c scan.c stmt.c tree.c | ||
cc -o comp1 -g cg.c expr.c gen.c main.c misc.c scan.c stmt.c tree.c | ||
|
||
compn: cgn.c expr.c gen.c main.c misc.c scan.c stmt.c tree.c | ||
cc -o compn -g cgn.c expr.c gen.c main.c misc.c scan.c stmt.c tree.c | ||
|
||
clean: | ||
rm -f comp1 *.o *.s out | ||
rm -f comp1 compn *.o *.s out | ||
|
||
test: comp1 input01 | ||
./comp1 input01 | ||
cc -o out out.s | ||
./out | ||
|
||
testn: compn input01 | ||
./compn input01 | ||
nasm -f elf64 out.s | ||
cc -no-pie -o out out.o | ||
./out |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
#include "defs.h" | ||
#include "data.h" | ||
#include "decl.h" | ||
|
||
// Code generator for x86-64 | ||
// Copyright (c) 2019 Warren Toomey, GPL3 | ||
|
||
|
||
// List of available registers | ||
// and their names | ||
static int freereg[4]; | ||
static char *reglist[4] = { "r8", "r9", "r10", "r11" }; | ||
|
||
// Set all registers as available | ||
void freeall_registers(void) { | ||
freereg[0] = freereg[1] = freereg[2] = freereg[3] = 1; | ||
} | ||
|
||
// Allocate a free register. Return the number of | ||
// the register. Die if no available registers. | ||
static int alloc_register(void) { | ||
for (int i = 0; i < 4; i++) { | ||
if (freereg[i]) { | ||
freereg[i] = 0; | ||
return (i); | ||
} | ||
} | ||
fprintf(stderr, "Out of registers!\n"); | ||
exit(1); | ||
} | ||
|
||
// Return a register to the list of available registers. | ||
// Check to see if it's not already there. | ||
static void free_register(int reg) { | ||
if (freereg[reg] != 0) { | ||
fprintf(stderr, "Error trying to free register %d\n", reg); | ||
exit(1); | ||
} | ||
freereg[reg] = 1; | ||
} | ||
|
||
// Print out the assembly preamble | ||
void cgpreamble() { | ||
freeall_registers(); | ||
fputs("\tglobal\tmain\n" | ||
"\textern\tprintf\n" | ||
"\tsection\t.text\n" | ||
"LC0:\tdb\t\"%d\",10,0\n" | ||
"printint:\n" | ||
"\tpush\trbp\n" | ||
"\tmov\trbp, rsp\n" | ||
"\tsub\trsp, 16\n" | ||
"\tmov\t[rbp-4], edi\n" | ||
"\tmov\teax, [rbp-4]\n" | ||
"\tmov\tesi, eax\n" | ||
"\tlea rdi, [rel LC0]\n" | ||
"\tmov eax, 0\n" | ||
"\tcall printf\n" | ||
"\tnop\n" | ||
"\tleave\n" | ||
"\tret\n" | ||
"\n" | ||
"main:\n" "\tpush\trbp\n" "\tmov rbp, rsp\n", Outfile); | ||
} | ||
|
||
// Print out the assembly postamble | ||
void cgpostamble() { | ||
fputs("\tmov eax, 0\n" "\tpop rbp\n" "\tret\n", Outfile); | ||
} | ||
|
||
// Load an integer literal value into a register. | ||
// Return the number of the register | ||
int cgload(int value) { | ||
|
||
// Get a new register | ||
int r = alloc_register(); | ||
|
||
// Print out the code to initialise it | ||
fprintf(Outfile, "\tmov\t%s, %d\n", reglist[r], value); | ||
return (r); | ||
} | ||
|
||
// Add two registers together and return | ||
// the number of the register with the result | ||
int cgadd(int r1, int r2) { | ||
fprintf(Outfile, "\tadd\t%s, %s\n", reglist[r2], reglist[r1]); | ||
free_register(r1); | ||
return (r2); | ||
} | ||
|
||
// Subtract the second register from the first and | ||
// return the number of the register with the result | ||
int cgsub(int r1, int r2) { | ||
fprintf(Outfile, "\tsub\t%s, %s\n", reglist[r1], reglist[r2]); | ||
free_register(r2); | ||
return (r1); | ||
} | ||
|
||
// Multiply two registers together and return | ||
// the number of the register with the result | ||
int cgmul(int r1, int r2) { | ||
fprintf(Outfile, "\timul\t%s, %s\n", reglist[r2], reglist[r1]); | ||
free_register(r1); | ||
return (r2); | ||
} | ||
|
||
// Divide the first register by the second and | ||
// return the number of the register with the result | ||
int cgdiv(int r1, int r2) { | ||
fprintf(Outfile, "\tmov\trax, %s\n", reglist[r1]); | ||
fprintf(Outfile, "\tcqo\n"); | ||
fprintf(Outfile, "\tidiv\t%s\n", reglist[r2]); | ||
fprintf(Outfile, "\tmov\t%s, rax\n", reglist[r1]); | ||
free_register(r2); | ||
return (r1); | ||
} | ||
|
||
// Call printint() with the given register | ||
void cgprintint(int r) { | ||
fprintf(Outfile, "\tmov\trdi, %s\n", reglist[r]); | ||
fprintf(Outfile, "\tcall\tprintint\n"); | ||
free_register(r); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.