scc

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

ins.c (5412B)


      1 #include <stdlib.h>
      2 #include <string.h>
      3 
      4 #include <scc/scc.h>
      5 
      6 #include "../../as.h"
      7 #include "proc.h"
      8 
      9 #define addrbyte(mod, reg, rm) ((mod) << 6 | (reg) << 3 | (rm))
     10 
     11 enum addr_mode {
     12 	MEM_MODE   = 0,
     13 	MEM8_MODE  = 1,
     14 	MEM16_MODE = 2,
     15 	REG_MODE   = 3,
     16 };
     17 
     18 static int
     19 getclass(Node *np)
     20 {
     21 	if (np->addr != AREG)
     22 		return 0;
     23 
     24 	switch (np->sym->value) {
     25 	case AREG_AL:
     26 	case AREG_AH:
     27 	case AREG_BL:
     28 	case AREG_BH:
     29 	case AREG_CL:
     30 	case AREG_CH:
     31 	case AREG_DL:
     32 	case AREG_DH:
     33 		return R8CLASS;
     34 
     35 	case AREG_AX:
     36 	case AREG_BX:
     37 	case AREG_CX:
     38 	case AREG_DX:
     39 	case AREG_DI:
     40 	case AREG_SI:
     41 	case AREG_SP:
     42 	case AREG_BP:
     43 		return R16CLASS;
     44 
     45 	case AREG_CS:
     46 	case AREG_DS:
     47 	case AREG_SS:
     48 	case AREG_ES:
     49 	case AREG_FS:
     50 	case AREG_GS:
     51 
     52 	case AREG_EFLAGS:
     53 	case AREG_CF:
     54 	case AREG_PF:
     55 	case AREG_AF:
     56 	case AREG_ZF:
     57 	case AREG_SF:
     58 	case AREG_TF:
     59 	case AREG_IF:
     60 	case AREG_DF:
     61 	case AREG_OF:
     62 	case AREG_IOPL:
     63 	case AREG_NT:
     64 	case AREG_RF:
     65 	case AREG_VM:
     66 	case AREG_AC:
     67 	case AREG_VIF:
     68 	case AREG_VIP:
     69 	case AREG_ID:
     70 
     71 	case AREG_EAX:
     72 	case AREG_RAX:
     73 
     74 	case AREG_EBX:
     75 	case AREG_RBX:
     76 
     77 	case AREG_ECX:
     78 	case AREG_RCX:
     79 
     80 	case AREG_EDX:
     81 	case AREG_RDX:
     82 
     83 	case AREG_SIL:
     84 	case AREG_ESI:
     85 	case AREG_RSI:
     86 	case AREG_DIL:
     87 	case AREG_EDI:
     88 	case AREG_RDI:
     89 
     90 	case AREG_SPL:
     91 	case AREG_ESP:
     92 	case AREG_RSP:
     93 
     94 	case AREG_BPL:
     95 	case AREG_EBP:
     96 	case AREG_RBP:
     97 
     98 	case AREG_R0:
     99 	case AREG_MM0:
    100 	case AREG_R1:
    101 	case AREG_MM1:
    102 	case AREG_R2:
    103 	case AREG_MM2:
    104 	case AREG_R3:
    105 	case AREG_MM3:
    106 	case AREG_R4:
    107 	case AREG_MM4:
    108 	case AREG_R5:
    109 	case AREG_MM5:
    110 	case AREG_R6:
    111 	case AREG_MM6:
    112 	case AREG_R7:
    113 	case AREG_MM7:
    114 
    115 	case AREG_R8:
    116 	case AREG_R8L:
    117 	case AREG_R8W:
    118 	case AREG_R9:
    119 	case AREG_R9L:
    120 	case AREG_R9W:
    121 	case AREG_R10:
    122 	case AREG_R10L:
    123 	case AREG_R10W:
    124 	case AREG_R11:
    125 	case AREG_R11L:
    126 	case AREG_R11W:
    127 	case AREG_R12:
    128 	case AREG_R12L:
    129 	case AREG_R12W:
    130 	case AREG_R13:
    131 	case AREG_R13L:
    132 	case AREG_R13W:
    133 	case AREG_R14:
    134 	case AREG_R14L:
    135 	case AREG_R14W:
    136 	case AREG_R15:
    137 	case AREG_R15L:
    138 	case AREG_R15W:
    139 
    140 	case AREG_XMM0:
    141 	case AREG_XMM1:
    142 	case AREG_XMM2:
    143 	case AREG_XMM3:
    144 	case AREG_XMM4:
    145 	case AREG_XMM5:
    146 	case AREG_XMM6:
    147 	case AREG_XMM7:
    148 	case AREG_XMM8:
    149 	case AREG_XMM9:
    150 	case AREG_XMM10:
    151 	case AREG_XMM11:
    152 	case AREG_XMM12:
    153 	case AREG_XMM13:
    154 	case AREG_XMM14:
    155 	case AREG_XMM15:
    156 
    157 	case AREG_YMM0:
    158 	case AREG_YMM1:
    159 	case AREG_YMM2:
    160 	case AREG_YMM3:
    161 	case AREG_YMM4:
    162 	case AREG_YMM5:
    163 	case AREG_YMM6:
    164 	case AREG_YMM7:
    165 	case AREG_YMM8:
    166 	case AREG_YMM9:
    167 	case AREG_YMM10:
    168 	case AREG_YMM11:
    169 	case AREG_YMM12:
    170 	case AREG_YMM13:
    171 	case AREG_YMM14:
    172 	case AREG_YMM15:
    173 
    174 	case AREG_MXCSR:
    175 		return 0;
    176 	default:
    177 		abort();
    178 	}
    179 }
    180 
    181 int
    182 match(Op *op, Node **args)
    183 {
    184 	unsigned char *p;
    185 	int arg, class, rep, opt;
    186 	Node *np;
    187 
    188 	if (!op->args)
    189 		return args == NULL;
    190 
    191 	opt = rep = 0;
    192 	for (p = op->args; arg = *p; ++p) {
    193 		if (rep)
    194 			--p;
    195 		if ((np = *args++) == NULL)
    196 			return (rep|opt) != 0;
    197 
    198 		switch (arg) {
    199 		case AOPT:
    200 			opt = 1;
    201 			break;
    202 		case AREP:
    203 			rep = 1;
    204 			break;
    205 		case AREG_R8CLASS:
    206 			class = R8CLASS;
    207 			goto check_class;
    208 		case AREG_R16CLASS:
    209 			class = R16CLASS;
    210 		check_class:
    211 			if ((getclass(np) & class) == 0)
    212 				return 0;
    213 			break;
    214 		case AIMM8:
    215 		case AIMM16:
    216 		case AIMM32:
    217 		case AIMM64:
    218 			if (np->addr != AIMM)
    219 				return 0;
    220 			if (toobig(np, arg))
    221 				error("overflow in immediate operand");
    222 			break;
    223 		case ASYM:
    224 			if (np->addr != AIMM || np->op != IDEN)
    225 				return 0;
    226 			break;
    227 		case ADIRECT:
    228 		case ASTR:
    229 			if (np->addr != arg)
    230 				return 0;
    231 			break;
    232 		default:
    233 			abort();
    234 		}
    235 	}
    236 
    237 	return *args == NULL;
    238 }
    239 
    240 Node *
    241 moperand(void)
    242 {
    243 }
    244 
    245 static int
    246 reg8toint(Node *np)
    247 {
    248 	switch (np->sym->value) {
    249 	case AREG_AL: return 0;
    250 	case AREG_CL: return 1;
    251 	case AREG_DL: return 2;
    252 	case AREG_BL: return 3;
    253 	case AREG_AH: return 4;
    254 	case AREG_CH: return 5;
    255 	case AREG_DH: return 6;
    256 	case AREG_BH: return 7;
    257 	default:      abort();
    258 	}
    259 }
    260 
    261 static int
    262 reg16toint(Node *np)
    263 {
    264 	switch (np->sym->value) {
    265 	case AREG_AX: return 0;
    266 	case AREG_CX: return 1;
    267 	case AREG_DX: return 2;
    268 	case AREG_BX: return 3;
    269 	case AREG_SP: return 4;
    270 	case AREG_BP: return 5;
    271 	case AREG_SI: return 6;
    272 	case AREG_DI: return 7;
    273 	default:	abort();
    274 	}
    275 }
    276 
    277 static int
    278 reg32toint(Node *np)
    279 {
    280 	switch (np->sym->value) {
    281 	case AREG_EAX: return 0;
    282 	case AREG_ECX: return 1;
    283 	case AREG_EDX: return 2;
    284 	case AREG_EBX: return 3;
    285 	case AREG_ESP: return 4;
    286 	case AREG_EBP: return 5;
    287 	case AREG_ESI: return 6;
    288 	case AREG_EDI: return 7;
    289 	default:	abort();
    290 	}
    291 }
    292 
    293 void
    294 reg8_reg8(Op *op, Node **args)
    295 {
    296 	int src, dst;
    297 	char buf[op->size];
    298 
    299 	src = reg8toint(args[0]);
    300 	dst = reg8toint(args[1]);
    301 	memcpy(buf, op->bytes, op->size - 1);
    302 	buf[op->size - 1] = addrbyte(REG_MODE, src, dst);
    303 	emit(buf, op->size);
    304 }
    305 
    306 void
    307 imm8_reg8(Op *op, Node **args)
    308 {
    309 	int src, dst;
    310 	char buf[op->size];
    311 
    312 	src = (*args)->sym->value;
    313 	dst = reg8toint(args[1]);
    314 	memcpy(buf, op->bytes, op->size - 2);
    315 	buf[op->size - 2] = addrbyte(REG_MODE, 0, dst);
    316 	buf[op->size - 1] = src;
    317 	emit(buf, op->size);
    318 }
    319 
    320 
    321 void
    322 reg16_reg16(Op *op, Node **args)
    323 {
    324 	int src, dst;
    325 	char buf[op->size];
    326 
    327 	src = reg16toint(args[0]);
    328 	dst = reg16toint(args[1]);
    329 	memcpy(buf, op->bytes, op->size - 1);
    330 	buf[op->size - 1] = addrbyte(REG_MODE, src, dst);
    331 	emit(buf, op->size);
    332 }
    333 
    334 
    335 void
    336 reg32_reg32(Op *op, Node **args)
    337 {
    338 	int src, dst;
    339 	char buf[op->size];
    340 
    341 	src = reg32toint(args[0]);
    342 	dst = reg32toint(args[1]);
    343 	memcpy(buf, op->bytes, op->size - 1);
    344 	buf[op->size - 1] = addrbyte(REG_MODE, src, dst);
    345 	emit(buf, op->size);
    346 }