scc

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

ins.c (9696B)


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