scc

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

ins.c (9688B)


      1 #include <stdlib.h>
      2 #include <string.h>
      3 
      4 #include <scc/mach.h>
      5 #include <scc/scc.h>
      6 
      7 #include "../as.h"
      8 #include "proc.h"
      9 
     10 /*
     11  * This implementation is based in:
     12  *	- Zilog Z80 CPU Specifications by Sean Young
     13  *	- Decoding Z80 opcodes - of use to disassembler and emulator
     14  *	  writers - by Cristian Dinu.
     15  */
     16 
     17 static int
     18 getclass(Node *np)
     19 {
     20 	if (np->addr != AREG)
     21 		return 0;
     22 
     23 	switch (np->sym->value) {
     24 	case AREG_C:
     25 		return RCLASS | PCLASS | QCLASS | CCCLASS | SSCLASS;
     26 	case AREG_A:
     27 	case AREG_B:
     28 	case AREG_D:
     29 	case AREG_E:
     30 		return RCLASS | PCLASS | QCLASS;
     31 	case AREG_H:
     32 	case AREG_L:
     33 		return RCLASS;
     34 	case AREG_IXL:
     35 	case AREG_IXH:
     36 		return PCLASS;
     37 	case AREG_IYL:
     38 	case AREG_IYH:
     39 		return QCLASS;
     40 	case AREG_HL:
     41 		return DDCLASS | QQCLASS;
     42 	case AREG_BC:
     43 	case AREG_DE:
     44 		return DDCLASS | QQCLASS | PPCLASS | RRCLASS;
     45 	case AREG_SP:
     46 		return DDCLASS | PPCLASS | RRCLASS;
     47 	case AREG_AF:
     48 		return QQCLASS;
     49 	case AREG_IX:
     50 		return PPCLASS;
     51 	case AREG_IY:
     52 		return RRCLASS;
     53 	case AREG_PO:
     54 	case AREG_PE:
     55 	case AREG_P:
     56 	case AREG_M:
     57 		return CCCLASS;
     58 	case AREG_NZ:
     59 	case AREG_Z:
     60 	case AREG_NC:
     61 		return CCCLASS | SSCLASS;
     62 	default:
     63 		return 0;
     64 	}
     65 }
     66 
     67 int
     68 match(Op *op, Node **args)
     69 {
     70 	unsigned char *p;
     71 	int arg, class, rep, opt;
     72 	Node *np;
     73 
     74 	if (!op->args)
     75 		return args == NULL;
     76 
     77 	opt = rep = 0;
     78 	for (p = op->args; arg = *p; ++p) {
     79 		if (rep)
     80 			--p;
     81 		if ((np = *args++) == NULL)
     82 			return (rep|opt) != 0;
     83 
     84 		switch (arg) {
     85 		case AOPT:
     86 			opt = 1;
     87 			break;
     88 		case AREP:
     89 			rep = 1;
     90 			break;
     91 		case AINDER_C:
     92 			arg = AREG_C;
     93 			goto indirect;
     94 		case AINDER_HL:
     95 			arg = AREG_HL;
     96 			goto indirect;
     97 		case AINDER_DE:
     98 			arg = AREG_DE;
     99 			goto indirect;
    100 		case AINDER_BC:
    101 			arg = AREG_BC;
    102 			goto indirect;
    103 		case AINDER_IX:
    104 			arg = AREG_IX;
    105 			goto indirect;
    106 		case AINDER_IY:
    107 			arg = AREG_IY;
    108 			goto indirect;
    109 		case AINDER_SP:
    110 			arg = AREG_SP;
    111 		indirect:
    112 			if (np->addr != AINDIR)
    113 				return 0;
    114 			np = np->left;
    115 		case AREG_A:
    116 		case AREG_I:
    117 		case AREG_R:
    118 		case AREG_F:
    119 		case AREG_HL:
    120 		case AREG_BC:
    121 		case AREG_DE:
    122 		case AREG_IY:
    123 		case AREG_IX:
    124 		case AREG_SP:
    125 		case AREG_AF:
    126 		case AREG_AF_:
    127 			if (np->addr != AREG || np->sym->value != arg)
    128 				return 0;
    129 			break;
    130 		case AREG_RCLASS:
    131 			class = RCLASS;
    132 			goto check_class;
    133 		case AREG_PCLASS:
    134 			class = PCLASS;
    135 			goto check_class;
    136 		case AREG_QCLASS:
    137 			class = QCLASS;
    138 			goto check_class;
    139 		case AREG_QQCLASS:
    140 			class = QQCLASS;
    141 			goto check_class;
    142 		case AREG_PPCLASS:
    143 			class = PPCLASS;
    144 			goto check_class;
    145 		case AREG_RRCLASS:
    146 			class = RRCLASS;
    147 			goto check_class;
    148 		case AREG_CCCLASS:
    149 			class = CCCLASS;
    150 			goto check_class;
    151 		case AREG_SSCLASS:
    152 			class = SSCLASS;
    153 			goto check_class;
    154 		case AREG_DDCLASS:
    155 			class = DDCLASS;
    156 		check_class:
    157 			if ((getclass(np) & class) == 0)
    158 				return 0;
    159 			break;
    160 		case AINDEX_IY:
    161 			arg = AREG_IY;
    162 			goto index_address;
    163 		case AINDEX_IX:
    164 			arg = AREG_IX;
    165 		index_address:
    166 			if (np->addr != AINDEX)
    167 				return 0;
    168 			np = np->left->left;
    169 			if (np->sym->value != arg)
    170 				return 0;
    171 			if (toobig(np, AIMM8))
    172 				error("overflow in index");
    173 			break;
    174 		case ARST:
    175 			if (np->addr != AIMM)
    176 				return 0;
    177 			if ((np->sym->value & ~0x38) != 0)
    178 				return 0;
    179 			break;
    180 		case AZERO:
    181 			if (np->addr != AIMM)
    182 				return 0;
    183 			break;
    184 		case AIMM3:
    185 		case AIMM8:
    186 		case AIMM16:
    187 		case AIMM32:
    188 		case AIMM64:
    189 			if (np->addr != AIMM)
    190 				return 0;
    191 			if (toobig(np, arg))
    192 				error("overflow in immediate operand");
    193 			break;
    194 		case ASYM:
    195 			if (np->op != IDEN)
    196 				return 0;
    197 			break;
    198 		case ADIRECT:
    199 		case ASTR:
    200 			if (np->addr != arg)
    201 				return 0;
    202 			break;
    203 		default:
    204 			abort();
    205 		}
    206 	}
    207 
    208 	return *args == NULL;
    209 }
    210 
    211 /*
    212  * (expr) -> ADIRECT
    213  * (REG)  -> AINDIR
    214  * (REG + expr) -> AINDEX
    215  * (REG - expr) -> AINDEX
    216  * expr (REG) -> AINDEX
    217  */
    218 Node *
    219 moperand(void)
    220 {
    221 	int op;
    222 	Node *np, *dir, *off, *reg;
    223 
    224 	dir = off = reg = NULL;
    225 	if (accept('(')) {
    226 		if (yytoken != REG) {
    227 			dir = expr();
    228 		} else {
    229 			reg = getreg();
    230 			switch (yytoken) {
    231 			case '+':
    232 			case '-':
    233 				off = expr();
    234 			case ')':
    235 				break;
    236 			default:
    237 				unexpected();
    238 			}
    239 		}
    240 	} else {
    241 		off = expr();
    242 		expect('(');
    243 		reg = getreg();
    244 	}
    245 	expect(')');
    246 
    247 	if (dir) {
    248 		op = ADIRECT;
    249 		np = dir;
    250 	} else if (off) {
    251 		np = node(AREG_OFF, reg, off);
    252 		op = AINDEX;
    253 	} else {
    254 		np = reg;
    255 		op = AINDIR;
    256 	}
    257 	np = node(op, np, NULL);
    258 	np->addr = op;
    259 	return np;
    260 }
    261 
    262 static int
    263 reg2int(Node *np)
    264 {
    265 	switch (np->sym->value) {
    266 	case AREG_F:
    267 	case AREG_B:   return 0;
    268 	case AREG_C:   return 1;
    269 	case AREG_D:   return 2;
    270 	case AREG_E:   return 3;
    271 	case AREG_IXH:
    272 	case AREG_IYH:
    273 	case AREG_H:   return 4;
    274 	case AREG_IXL:
    275 	case AREG_IYL:
    276 	case AREG_L:   return 5;
    277 	case AREG_A:   return 7;
    278 	case AREG_BC:  return 0;
    279 	case AREG_DE:  return 1;
    280 	case AREG_HL:
    281 	case AREG_IX:
    282 	case AREG_IY:  return 2;
    283 	case AREG_AF:
    284 	case AREG_SP:  return 3;
    285 	default:       abort();
    286 	}
    287 }
    288 
    289 static int
    290 cc2int(Node *np)
    291 {
    292 	switch (np->sym->value) {
    293 	case AREG_NZ:  return 0;
    294 	case AREG_Z:   return 1;
    295 	case AREG_NC:  return 2;
    296 	case AREG_C:   return 3;
    297 	case AREG_PO:  return 4;
    298 	case AREG_PE:  return 5;
    299 	case AREG_P:   return 6;
    300 	case AREG_M:   return 7;
    301 	default:       abort();
    302 	}
    303 }
    304 
    305 static int
    306 ss2int(Node *np)
    307 {
    308 	switch (np->sym->value) {
    309 	case AREG_NZ:  return 4;
    310 	case AREG_Z:   return 5;
    311 	case AREG_NC:  return 6;
    312 	case AREG_C:   return 7;
    313 	default:       abort();
    314 	}
    315 }
    316 
    317 void
    318 dir(Op *op, Node **args)
    319 {
    320 	Node *imm;
    321 	unsigned char buf[4];
    322 	unsigned val;
    323 	int n = op->size;
    324 
    325 	imm = (args[1]->addr == ADIRECT) ? args[1] : args[0];
    326 	imm = imm->left;
    327 	memcpy(buf, op->bytes, n);
    328 	val = imm->sym->value;
    329 	buf[n-1] = val >> 8;
    330 	buf[n-2] = val;
    331 	emit(buf, n);
    332 }
    333 
    334 void
    335 ld8(Op *op, Node **args)
    336 {
    337 	Node *par1 = args[0], *par2 = args[1];
    338 	int n = op->size, i = n;
    339 	unsigned regval = 0;
    340 	unsigned char buf[4];
    341 
    342 	memcpy(buf, op->bytes, n);
    343 
    344 	if (par1->addr == AREG)
    345 		regval |= reg2int(par1) << 3;
    346 	if (par2->addr == AREG)
    347 		regval |= reg2int(par2);
    348 	else if (par2->addr == AIMM)
    349 		buf[--i] = par2->sym->value;
    350 
    351 	buf[--i] |= regval;
    352 	emit(buf, n);
    353 }
    354 
    355 void
    356 alu16(Op *op, Node **args)
    357 {
    358 	Node *par;
    359 	int n = op->size;
    360 	unsigned val;
    361 	unsigned char buf[4];
    362 
    363 	par = (args[1]) ? args[1] : args[0];
    364 	val = reg2int(par);
    365 	memcpy(buf, op->bytes, n);
    366 	buf[n-1] |= val << 4;
    367 	emit(buf, n);
    368 }
    369 
    370 void
    371 ld16(Op *op, Node **args)
    372 {
    373 	Node *dst, *src, *tmp;
    374 	int n = op->size;
    375 	unsigned val;
    376 	unsigned char buf[4];
    377 
    378 	dst = args[0];
    379 	src = args[1];
    380 	if (!src) {
    381 		alu16(op, args);
    382 		return;
    383 	}
    384 
    385 	if (dst->addr != AREG) {
    386 		tmp = src;
    387 		src = dst;
    388 		dst = tmp;
    389 	}
    390 
    391 	memcpy(buf, op->bytes, n);
    392 	if (src->addr == ADIRECT)
    393 		src = src->left;
    394 	val = src->sym->value;
    395 	buf[n-1] = val >> 8;
    396 	buf[n-2] = val;
    397 	buf[n-3] |= reg2int(dst) << 4;
    398 	emit(buf, n);
    399 }
    400 
    401 void
    402 alu8(Op *op, Node **args)
    403 {
    404 	Node *par = args[1];
    405 	unsigned char buf[4];
    406 	int n = op->size, shift;
    407 	unsigned val;
    408 
    409 	if (args[1]) {
    410 		shift = 0;
    411 		par = args[1];
    412 	} else {
    413 		shift = 3;
    414 		par = args[0];
    415 	}
    416 
    417 	switch (par->addr) {
    418 	case AIMM:
    419 		val = par->sym->value;
    420 		break;
    421 	case AREG:
    422 		val = reg2int(par) << shift;
    423 		break;
    424 	case AINDEX:
    425 		val = par->left->right->sym->value;
    426 		break;
    427 	case AINDIR:
    428 		val = 0;
    429 		break;
    430 	default:
    431 		abort();
    432 	}
    433 
    434 	memcpy(buf, op->bytes, n);
    435 	buf[n-1] |= val;
    436 	emit(buf, n);
    437 }
    438 
    439 void
    440 idx(Op *op, Node **args)
    441 {
    442 	Node *tmp, *idx, *imm, *reg;
    443 	unsigned char buf[4];
    444 	int n = op->size, i = n, shift = 0;
    445 
    446 	imm = reg = NULL;
    447 	if (args[0]->addr != AINDEX) {
    448 		shift = 3;
    449 		tmp = args[0];
    450 		args[0] = args[1];
    451 		args[1] = tmp;
    452 	}
    453 	idx = args[0]->left->right;
    454 
    455 	if (args[1]->addr == AREG)
    456 		reg = args[1];
    457 	else
    458 		imm = args[1];
    459 
    460 	memcpy(buf, op->bytes, n);
    461 
    462 	if (imm)
    463 		buf[--i] = imm->sym->value;
    464 	buf[--i] = idx->sym->value;
    465 	if (reg)
    466 		buf[--i] |= reg2int(reg) << shift;
    467 
    468 	emit(buf, n);
    469 }
    470 
    471 void
    472 inout(Op *op, Node **args)
    473 {
    474 	Node *port, *value;
    475 	unsigned val;
    476 	int n = op->size;
    477 	unsigned char buf[5];
    478 
    479 	port = args[0];
    480 	value = args[1];
    481 	if (port->addr != ADIRECT && port->addr != AINDIR) {
    482 		value = port;
    483 		port = args[1];
    484 	}
    485 
    486 	if (port->addr == ADIRECT)
    487 		val = port->left->sym->value;
    488 	else if (value->addr == AREG)
    489 		val = reg2int(value) << 3;
    490 	else
    491 		val = 0;
    492 
    493 	memcpy(buf, op->bytes, n);
    494 	buf[n-1] |= val;
    495 	emit(buf, n);
    496 }
    497 
    498 void
    499 rot_bit(Op *op, Node **args)
    500 {
    501 	Node *par = args[0];
    502 	unsigned char buf[5];
    503 	int n = op->size;
    504 	unsigned val, npar = 0;
    505 
    506 	memcpy(buf, op->bytes, n);
    507 
    508 	par = args[0];
    509 	if (par->addr == AIMM) {
    510 		buf[n-1] |= par->sym->value << 3;
    511 		par = args[npar = 1];
    512 	}
    513 
    514 	switch (par->addr) {
    515 	case AINDEX:
    516 		val = par->left->right->sym->value;
    517 		buf[n-2] = val;
    518 		par = args[npar+1];
    519 		if (!par)
    520 			break;
    521 	case AREG:
    522 		val = reg2int(par);
    523 		buf[n-1] |= val;
    524 	case AINDIR:
    525 		break;
    526 	default:
    527 		abort();
    528 	}
    529 
    530 	emit(buf, n);
    531 }
    532 
    533 void
    534 im(Op *op, Node **args)
    535 {
    536 	unsigned val = args[0]->sym->value;
    537 	unsigned char buf[4];
    538 	int n = op->size;
    539 
    540 	if (val > 0)
    541 		++val;
    542 
    543 	memcpy(buf, op->bytes, n);
    544 	buf[n-1] |= val << 3;
    545 	emit(buf, n);
    546 }
    547 
    548 void
    549 branch(int relative, Op *op, Node **args)
    550 {
    551 	unsigned char buf[4];
    552 	Node *flag, *imm;
    553 	int n = op->size, i = n;
    554 	unsigned val;
    555 	int (*fun)(Node *);
    556 
    557 	flag = imm = NULL;
    558 	if (args[0]->addr == AREG) {
    559 		flag = args[0];
    560 		imm = args[1];
    561 	} else if (args[0]->addr == AIMM) {
    562 		imm = args[0];
    563 	}
    564 	memcpy(buf, op->bytes, n);
    565 
    566 	if (imm) {
    567 		val = imm->sym->value;
    568 		if (!relative)
    569 			buf[--i] = val >> 8;
    570 		else
    571 			val -= getpc() - 2;
    572 		buf[--i] = val;
    573 
    574 	}
    575 	if (flag) {
    576 		fun = (relative) ? ss2int : cc2int;
    577 		buf[--i] |= (*fun)(flag) << 3;
    578 	}
    579 
    580 
    581 	emit(buf, n);
    582 }
    583 
    584 void
    585 jp(Op *op, Node **args)
    586 {
    587 	branch(0, op, args);
    588 }
    589 
    590 void
    591 jr(Op *op, Node **args)
    592 {
    593 	branch(1, op, args);
    594 }
    595 
    596 void
    597 rst(Op *op, Node **args)
    598 {
    599 	unsigned char buf[1];
    600 
    601 	buf[0] = op->bytes[0];
    602 	buf[0] |= args[0]->sym->value;
    603 	emit(buf, 1);
    604 }