aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--asm.peg8
-rw-r--r--main.c30
-rw-r--r--minias.h20
-rw-r--r--test/test.sh6
4 files changed, 57 insertions, 7 deletions
diff --git a/asm.peg b/asm.peg
index d87dd7b..a4db0a5 100644
--- a/asm.peg
+++ b/asm.peg
@@ -24,7 +24,11 @@ directive =
| "balign" ws n:number
{ $$.balign = (Balign){.kind = ASM_DIR_BALIGN, .align = n.i64 }; }
| "byte" ws n:number
- { $$.byte = (Byte){.kind = ASM_DIR_BYTE, .b = (uint8_t)n.i64 }; }
+ { $$.dirbyte = (Byte){.kind = ASM_DIR_BYTE, .v = n.i64 }; }
+ | "int" ws n:number
+ { $$.dirint = (Int){.kind = ASM_DIR_INT, .v = n.i64 }; }
+ | "quad" ws n:number
+ { $$.dirquad = (Quad){.kind = ASM_DIR_QUAD, .v = n.i64 }; }
| sd:section-directive { $$ = sd; }
section-directive =
@@ -52,6 +56,8 @@ instr =
"nop" { $$.kind = ASM_NOP; }
| "leave" { $$.kind = ASM_LEAVE; }
| "ret" { $$.kind = ASM_RET; }
+ | "cltd" { $$.kind = ASM_CLTD; }
+ | "cqto" { $$.kind = ASM_CQTO; }
| i:push { $$ = i; }
| i:pop { $$ = i; }
| i:call { $$ = i; }
diff --git a/main.c b/main.c
index b344802..282c0eb 100644
--- a/main.c
+++ b/main.c
@@ -293,6 +293,20 @@ static void su32(uint32_t l) {
secaddbytes(cursection, buf, sizeof(buf));
}
+static void su64(uint32_t l) {
+ uint8_t buf[8] = {
+ l & 0xff,
+ (l & 0xff00) >> 8,
+ (l & 0xff00) >> 16,
+ (l & 0xff000000) >> 24,
+ (l & 0xff00000000) >> 32,
+ (l & 0xff0000000000) >> 40,
+ (l & 0xff000000000000) >> 48,
+ (l & 0xff00000000000000) >> 56,
+ };
+ secaddbytes(cursection, buf, sizeof(buf));
+}
+
/* Convert an AsmKind to register bits in reg/rm style. */
static uint8_t regbits(AsmKind k) { return (k - (ASM_REG_BEGIN + 1)) % 16; }
@@ -332,7 +346,7 @@ void assembleconstant(int64_t c, int nbytes) {
su32((uint32_t)c);
break;
case 8:
- fatal("TODO 8 byte");
+ su64((uint64_t)c);
break;
default:
unreachable();
@@ -651,7 +665,13 @@ static void assemble(void) {
break;
}
case ASM_DIR_BYTE:
- sb(v->byte.b);
+ sb((uint8_t)v->dirbyte.v);
+ break;
+ case ASM_DIR_INT:
+ su32((uint32_t)v->dirint.v);
+ break;
+ case ASM_DIR_QUAD:
+ su64((uint64_t)v->dirquad.v);
break;
case ASM_LABEL:
sym = getsym(v->label.name);
@@ -705,6 +725,12 @@ static void assemble(void) {
case ASM_LEAVE:
sb(0xc9);
break;
+ case ASM_CLTD:
+ sb(0x99);
+ break;
+ case ASM_CQTO:
+ sb2(0x48, 0x99);
+ break;
case ASM_RET:
sb(0xc3);
break;
diff --git a/minias.h b/minias.h
index 4d05a03..83eea1a 100644
--- a/minias.h
+++ b/minias.h
@@ -53,6 +53,8 @@ typedef enum {
ASM_DIR_DATA,
ASM_DIR_TEXT,
ASM_DIR_BYTE,
+ ASM_DIR_INT,
+ ASM_DIR_QUAD,
ASM_DIR_BALIGN,
// Instructions
ASM_NOP,
@@ -60,6 +62,8 @@ typedef enum {
ASM_PUSH,
ASM_POP,
ASM_CALL,
+ ASM_CLTD,
+ ASM_CQTO,
ASM_JMP,
ASM_LEAVE,
ASM_ADD,
@@ -181,11 +185,21 @@ typedef struct {
typedef struct {
AsmKind kind;
- uint8_t b;
+ int64_t v;
} Byte;
typedef struct {
AsmKind kind;
+ int64_t v;
+} Int;
+
+typedef struct {
+ AsmKind kind;
+ int64_t v;
+} Quad;
+
+typedef struct {
+ AsmKind kind;
uint64_t align;
} Balign;
@@ -242,7 +256,9 @@ union Parsev {
Instr instr;
Call call;
Jmp jmp;
- Byte byte;
+ Byte dirbyte;
+ Int dirint;
+ Quad dirquad;
Imm imm;
String string;
// Temporary values.
diff --git a/test/test.sh b/test/test.sh
index b3346e7..448a77c 100644
--- a/test/test.sh
+++ b/test/test.sh
@@ -30,6 +30,10 @@ t () {
echo -n "."
}
+t "ret"
+t "cltd"
+t "cqto"
+
conditioncodes="
a ae b be c e
z g ge l le na
@@ -45,7 +49,6 @@ do
t "set${cc} (%rax)"
done
-
for op in sal sar shl shr
do
t "${op} \$3, %rax"
@@ -95,7 +98,6 @@ t "popq (%r9)"
t "popq %r9"
t "popq %rax"
-
t "movb \$127, (%rsp)"
t "movb \$127, (%rbp)"
t "movb \$127, 2147483647(%rsp)"