scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit ad5ff8712dc62f69cdd0d84822fdd04aa4a0f69d
parent 4eb5378e2f513589a9c0664544f2b87b3208aedc
Author: zerous Naveen Narayanan <zerous@nocebo.space>
Date:   Sun,  6 Jan 2019 13:56:59 +0100

[as/x86] Add more ADD instructions

ADDB	0x80
ADDW	0x66,0x01
ADDL	0x01

Diffstat:
Msrc/as/target/x86/ins.c | 79++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Msrc/as/target/x86/proc.h | 6++++--
Msrc/as/target/x86/rules.dat | 1+
Msrc/as/target/x86/x86.dat | 7+++++--
4 files changed, 72 insertions(+), 21 deletions(-)

diff --git a/src/as/target/x86/ins.c b/src/as/target/x86/ins.c @@ -259,19 +259,6 @@ reg8toint(Node *np) } } -void -reg8_reg8(Op *op, Node **args) -{ - int src, dst; - char buf[2]; - - src = reg8toint(args[0]); - dst = reg8toint(args[1]); - buf[0] = op->bytes[0]; - buf[1] = addrbyte(REG_MODE, src, dst); - emit(buf, 2); -} - static int reg16toint(Node *np) { @@ -288,15 +275,73 @@ reg16toint(Node *np) } } +static int +reg32toint(Node *np) +{ + switch (np->sym->value) { + case AREG_EAX: return 0; + case AREG_ECX: return 1; + case AREG_EDX: return 2; + case AREG_EBX: return 3; + case AREG_ESP: return 4; + case AREG_EBP: return 5; + case AREG_ESI: return 6; + case AREG_EDI: return 7; + default: abort(); + } +} + +void +reg8_reg8(Op *op, Node **args) +{ + int src, dst; + char buf[op->size]; + + src = reg8toint(args[0]); + dst = reg8toint(args[1]); + memcpy(buf, op->bytes, op->size - 1); + buf[op->size - 1] = addrbyte(REG_MODE, src, dst); + emit(buf, op->size); +} + +void +imm8_reg8(Op *op, Node **args) +{ + int src, dst; + char buf[op->size]; + + src = (*args)->sym->value; + dst = reg8toint(args[1]); + memcpy(buf, op->bytes, op->size - 2); + buf[op->size - 2] = addrbyte(REG_MODE, 0, dst); + buf[op->size - 1] = src; + emit(buf, op->size); +} + + void reg16_reg16(Op *op, Node **args) { int src, dst; - char buf[2]; + char buf[op->size]; src = reg16toint(args[0]); dst = reg16toint(args[1]); - buf[0] = op->bytes[0]; - buf[1] = addrbyte(REG_MODE, src, dst); - emit(buf, 2); + memcpy(buf, op->bytes, op->size - 1); + buf[op->size - 1] = addrbyte(REG_MODE, src, dst); + emit(buf, op->size); +} + + +void +reg32_reg32(Op *op, Node **args) +{ + int src, dst; + char buf[op->size]; + + src = reg32toint(args[0]); + dst = reg32toint(args[1]); + memcpy(buf, op->bytes, op->size - 1); + buf[op->size - 1] = addrbyte(REG_MODE, src, dst); + emit(buf, op->size); } diff --git a/src/as/target/x86/proc.h b/src/as/target/x86/proc.h @@ -146,11 +146,13 @@ enum args { AREG_MXCSR, - AREG_R8CLASS, /* register class for 8 bit registers in i286 */ - AREG_R16CLASS, /* register class for 16 bit registers in i286 */ + AREG_R8CLASS, /* register class for 8 bit registers in i286 */ + AREG_R16CLASS, /* register class for 16 bit registers in i286,i386,amd64 */ + AREG_R32CLASS, /* register class for 32 bit registers in i386,amd64 */ }; enum class { R8CLASS = 1 << 0, R16CLASS = 1 << 1, + R32CLASS = 1 << 2, }; diff --git a/src/as/target/x86/rules.dat b/src/as/target/x86/rules.dat @@ -1,5 +1,6 @@ reg8 AREG_R8CLASS reg16 AREG_R16CLASS +reg32 AREG_R32CLASS imm8 AIMM8 imm16 AIMM16 imm32 AIMM32 diff --git a/src/as/target/x86/x86.dat b/src/as/target/x86/x86.dat @@ -24,5 +24,8 @@ RET none 1 0xc3 noargs I286,I386,AMD64 # 8 bit arithmetic operations -ADDB reg8,reg8 2 0x00 reg8_reg8 I286,I386,AMD64 -ADDW reg16,reg16 2 0x01 reg16_reg16 I286,I386,AMD64 +ADDB reg8,reg8 2 0x00 reg8_reg8 I286,I386,AMD64 +ADDB imm8,reg8 3 0x80 imm8_reg8 I286,I386,AMD64 +ADDW reg16,reg16 2 0x01 reg16_reg16 I286 +ADDW reg16,reg16 3 0x66,0x01 reg16_reg16 I386,AMD64 +ADDL reg32,reg32 2 0x01 reg32_reg32 I386,AMD64