commit ec7dafa82296ddd9c75a487dc7c94e5701f1bd12
parent ff44515007b9436695136c7cb97009409b5fe45f
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Sun, 26 Dec 2021 16:10:49 -0600
i16
Diffstat:
M | main.c | | | 33 | +++++++++++++++++++++++++++++++++ |
M | type.c | | | 4 | ++++ |
M | x64.c | | | 86 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | x64.h | | | 6 | ++++++ |
4 files changed, 129 insertions(+), 0 deletions(-)
diff --git a/main.c b/main.c
@@ -113,6 +113,9 @@ place_move(char *buf, struct place *dest, struct place *src)
case 4:
total += mov_mr32_r32(buf ? buf + total : NULL, dest->l.reg, src->l.reg);
break;
+ case 2:
+ total += mov_mr16_r16(buf ? buf + total : NULL, dest->l.reg, src->l.reg);
+ break;
default:
die("place_move: REG -> REGADDR: unhandled size");
}
@@ -125,6 +128,9 @@ place_move(char *buf, struct place *dest, struct place *src)
case 4:
total += mov_disp8_m32_r32(buf ? buf + total : NULL, RBP, -dest->l.off, src->l.reg);
break;
+ case 2:
+ total += mov_disp8_m16_r16(buf ? buf + total : NULL, RBP, -dest->l.off, src->l.reg);
+ break;
default:
die("place_move: REG -> REGADDR: unhandled size");
}
@@ -153,6 +159,15 @@ place_move(char *buf, struct place *dest, struct place *src)
die("place_move: unhandled dest case for PLACE_REGADDR");
}
break;
+ case 2:
+ switch (dest->kind) {
+ case PLACE_REG:
+ total += mov_r16_mr16(buf ? buf + total : NULL, dest->l.reg, src->l.reg);
+ break;
+ default:
+ die("place_move: unhandled dest case for PLACE_REGADDR");
+ }
+ break;
default:
die("place_move: REGADDR: src unhandled size");
}
@@ -177,6 +192,15 @@ place_move(char *buf, struct place *dest, struct place *src)
die("place_move: unhandled dest case for PLACE_FRAME");
}
break;
+ case 2:
+ switch (dest->kind) {
+ case PLACE_REG:
+ total += mov_disp8_r16_m16(buf ? buf + total : NULL, dest->l.reg, RBP, -src->l.off);
+ break;
+ default:
+ die("place_move: unhandled dest case for PLACE_FRAME");
+ }
+ break;
default:
die("place_move: FRAME: src unhandled size");
}
@@ -201,6 +225,15 @@ place_move(char *buf, struct place *dest, struct place *src)
die("place_move: unhandled dest case for PLACE_ABS");
}
break;
+ case 2:
+ switch (dest->kind) {
+ case PLACE_REG:
+ total += mov_r16_m16(buf ? buf + total : NULL, dest->l.reg, src->l.addr);
+ break;
+ default:
+ die("place_move: unhandled dest case for PLACE_ABS");
+ }
+ break;
default:
die("place_move: ABS: src unhandled size");
}
diff --git a/type.c b/type.c
@@ -52,6 +52,10 @@ inittypes()
mapkey(&key, "i32", 3);
mapput(typesmap, &key)->n = idx;
+ type.class = TYPE_INT;
+ type.size = 2;
+ idx = type_put(&type);
+ mapkey(&key, "i16", 3);
mapput(typesmap, &key)->n = idx;
type.class = TYPE_STR;
diff --git a/x64.c b/x64.c
@@ -22,6 +22,8 @@ enum mod {
MOD_DIRECT
};
+#define OP_SIZE_OVERRIDE 0x66
+
char abi_arg[] = {RAX, RDI, RSI, RDX, R10, R8, R9};
unsigned short used_reg;
@@ -101,6 +103,19 @@ mov_r32_imm(char *buf, enum reg dest, uint32_t imm)
}
size_t
+mov_r16_imm(char *buf, enum reg dest, uint16_t imm)
+{
+ if (buf) {
+ *(buf++) = OP_SIZE_OVERRIDE;
+ *(buf++) = 0xb8;
+ *(buf++) = imm & 0xFF;
+ *(buf++) = (imm >> 8) & 0xFF;
+ }
+
+ return 4;
+}
+
+size_t
mov_r64_m64(char *buf, enum reg dest, uint64_t addr)
{
uint8_t sib = 0x25;
@@ -136,6 +151,24 @@ mov_r32_m32(char *buf, enum reg dest, uint32_t addr)
}
size_t
+mov_r16_m16(char *buf, enum reg dest, uint32_t addr)
+{
+ if (buf) {
+ *(buf++) = OP_SIZE_OVERRIDE;
+ if (dest >= 8) *(buf++) = REX_R;
+ *(buf++) = 0x8b;
+ *(buf++) = (MOD_INDIRECT << 6) | ((dest & 7) << 3) | 4;
+ *(buf++) = 0x25;
+ *(buf++) = addr & 0xFF;
+ *(buf++) = (addr >> 8) & 0xFF;
+ *(buf++) = (addr >> 16) & 0xFF;
+ *(buf++) = (addr >> 24) & 0xFF;
+ }
+
+ return dest >= 8 ? 9 : 8;
+}
+
+size_t
mov_m64_r64(char *buf, uint64_t addr, enum reg src)
{
if (buf) {
@@ -196,6 +229,18 @@ mov_mr32_r32(char *buf, enum reg dest, enum reg src)
}
size_t
+mov_mr16_r16(char *buf, enum reg dest, enum reg src)
+{
+ if (buf) {
+ *(buf++) = OP_SIZE_OVERRIDE;
+ *(buf++) = 0x8B;
+ *(buf++) = (MOD_INDIRECT << 6) | (src << 3) | dest;
+ }
+
+ return 3;
+}
+
+size_t
mov_r64_mr64(char *buf, enum reg dest, enum reg src)
{
if (buf) {
@@ -219,6 +264,18 @@ mov_r32_mr32(char *buf, enum reg dest, enum reg src)
}
size_t
+mov_r16_mr16(char *buf, enum reg dest, enum reg src)
+{
+ if (buf) {
+ *(buf++) = OP_SIZE_OVERRIDE;
+ *(buf++) = 0x89;
+ *(buf++) = (MOD_INDIRECT << 6) | (dest << 3) | src;
+ }
+
+ return 3;
+}
+
+size_t
mov_r64_r64(char *buf, enum reg dest, enum reg src)
{
if (buf) {
@@ -270,6 +327,21 @@ mov_disp8_m32_r32(char *buf, enum reg dest, int8_t disp, enum reg src)
return 3;
}
+// FIXME: we don't handle r8-r15 properly in most of these
+size_t
+mov_disp8_m16_r16(char *buf, enum reg dest, int8_t disp, enum reg src)
+{
+ assert(src != 4);
+ if (buf) {
+ *(buf++) = OP_SIZE_OVERRIDE;
+ *(buf++) = 0x89;
+ *(buf++) = (MOD_DISP8 << 6) | (src << 3) | dest;
+ *(buf++) = disp;
+ }
+
+ return 4;
+}
+
size_t
mov_disp8_r64_m64(char *buf, enum reg dest, enum reg src, int8_t disp)
{
@@ -298,6 +370,20 @@ mov_disp8_r32_m32(char *buf, enum reg dest, enum reg src, int8_t disp)
}
size_t
+mov_disp8_r16_m16(char *buf, enum reg dest, enum reg src, int8_t disp)
+{
+ assert(src != 4);
+ if (buf) {
+ *(buf++) = OP_SIZE_OVERRIDE;
+ *(buf++) = 0x8b;
+ *(buf++) = (MOD_DISP8 << 6) | (dest << 3) | src;
+ *(buf++) = disp;
+ }
+
+ return 4;
+}
+
+size_t
add_r64_r64(char *buf, enum reg dest, enum reg src)
{
if (buf) {
diff --git a/x64.h b/x64.h
@@ -28,17 +28,23 @@ size_t add_r64_imm(char *buf, enum reg reg, uint64_t imm);
size_t mov_r64_imm(char *buf, enum reg reg, uint64_t imm);
size_t mov_r64_m64(char *buf, enum reg reg, uint64_t addr);
size_t mov_r32_m32(char *buf, enum reg dest, uint32_t addr);
+size_t mov_r16_m16(char *buf, enum reg dest, uint32_t addr);
size_t mov_m64_r64(char *buf, uint64_t addr, enum reg reg);
size_t mov_m32_r32(char *buf, uint64_t addr, enum reg src);
+size_t mov_m16_r16(char *buf, uint64_t addr, enum reg src);
size_t mov_mr64_r64(char *buf, enum reg dest, enum reg src);
size_t mov_mr32_r32(char *buf, enum reg dest, enum reg src);
+size_t mov_mr16_r16(char *buf, enum reg dest, enum reg src);
size_t mov_r64_mr64(char *buf, enum reg dest, enum reg src);
size_t mov_r32_mr32(char *buf, enum reg dest, enum reg src);
+size_t mov_r16_mr16(char *buf, enum reg dest, enum reg src);
size_t mov_r64_r64(char *buf, enum reg dest, enum reg src);
size_t mov_disp8_m64_r64(char *buf, enum reg dest, int8_t disp, enum reg src);
size_t mov_disp8_m32_r32(char *buf, enum reg dest, int8_t disp, enum reg src);
+size_t mov_disp8_m16_r16(char *buf, enum reg dest, int8_t disp, enum reg src);
size_t mov_disp8_r64_m64(char *buf, enum reg dest, enum reg src, int8_t disp);
size_t mov_disp8_r32_m32(char *buf, enum reg dest, enum reg src, int8_t disp);
+size_t mov_disp8_r16_m16(char *buf, enum reg dest, enum reg src, int8_t disp);
size_t add_r64_r64(char *buf, enum reg reg1, enum reg reg2);
size_t sub_r64_r64(char *buf, enum reg reg1, enum reg reg2);
size_t sub_r64_imm(char *buf, enum reg reg1, int32_t imm);