scc

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

ins.c (9633B)


      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 			if (np->left->left->sym->value != arg)
    168 				return 0;
    169 			if (toobig(np, arg))
    170 				error("overflow in index");
    171 			break;
    172 		case ARST:
    173 			if (np->addr != AIMM)
    174 				return 0;
    175 			if ((np->sym->value & ~0x38) != 0)
    176 				return 0;
    177 			break;
    178 		case AZERO:
    179 		case AIMM3:
    180 		case AIMM8:
    181 		case AIMM16:
    182 		case AIMM32:
    183 		case AIMM64:
    184 			if (np->addr != AIMM)
    185 				return 0;
    186 			if (toobig(np, arg))
    187 				error("overflow in immediate operand");
    188 			break;
    189 		case ASYM:
    190 			if (np->addr != AIMM || np->op != IDEN)
    191 				return 0;
    192 			break;
    193 		case ADIRECT:
    194 		case ASTR:
    195 			if (np->addr != arg)
    196 				return 0;
    197 			break;
    198 		default:
    199 			abort();
    200 		}
    201 	}
    202 
    203 	return *args == NULL;
    204 }
    205 
    206 /*
    207  * (expr) -> ADIRECT
    208  * (REG)  -> AINDIR
    209  * (REG + expr) -> AINDEX
    210  * (REG - expr) -> AINDEX
    211  * expr (REG) -> AINDEX
    212  */
    213 Node *
    214 moperand(void)
    215 {
    216 	int op;
    217 	Node *np, *dir, *off, *reg;
    218 
    219 	dir = off = reg = NULL;
    220 	if (accept('(')) {
    221 		if (yytoken != REG) {
    222 			dir = expr();
    223 		} else {
    224 			reg = getreg();
    225 			switch (yytoken) {
    226 			case '+':
    227 			case '-':
    228 				off = expr();
    229 			case ')':
    230 				break;
    231 			default:
    232 				unexpected();
    233 			}
    234 		}
    235 	} else {
    236 		off = expr();
    237 		expect('(');
    238 		reg = getreg();
    239 	}
    240 	expect(')');
    241 
    242 	if (dir) {
    243 		op = ADIRECT;
    244 		np = dir;
    245 	} else if (off) {
    246 		np = node(AREG_OFF, reg, off);
    247 		op = AINDEX;
    248 	} else {
    249 		np = reg;
    250 		op = AINDIR;
    251 	}
    252 	np = node(op, np, NULL);
    253 	np->addr = op;
    254 	return np;
    255 }
    256 
    257 static int
    258 reg2int(Node *np)
    259 {
    260 	switch (np->sym->value) {
    261 	case AREG_F:
    262 	case AREG_B:   return 0;
    263 	case AREG_C:   return 1;
    264 	case AREG_D:   return 2;
    265 	case AREG_E:   return 3;
    266 	case AREG_IXH:
    267 	case AREG_IYH:
    268 	case AREG_H:   return 4;
    269 	case AREG_IXL:
    270 	case AREG_IYL:
    271 	case AREG_L:   return 5;
    272 	case AREG_A:   return 7;
    273 	case AREG_BC:  return 0;
    274 	case AREG_DE:  return 1;
    275 	case AREG_HL:
    276 	case AREG_IX:
    277 	case AREG_IY:  return 2;
    278 	case AREG_AF:
    279 	case AREG_SP:  return 3;
    280 	default:       abort();
    281 	}
    282 }
    283 
    284 static int
    285 cc2int(Node *np)
    286 {
    287 	switch (np->sym->value) {
    288 	case AREG_NZ:  return 0;
    289 	case AREG_Z:   return 1;
    290 	case AREG_NC:  return 2;
    291 	case AREG_C:   return 3;
    292 	case AREG_PO:  return 4;
    293 	case AREG_PE:  return 5;
    294 	case AREG_P:   return 6;
    295 	case AREG_M:   return 7;
    296 	default:       abort();
    297 	}
    298 }
    299 
    300 static int
    301 ss2int(Node *np)
    302 {
    303 	switch (np->sym->value) {
    304 	case AREG_NZ:  return 4;
    305 	case AREG_Z:   return 5;
    306 	case AREG_NC:  return 6;
    307 	case AREG_C:   return 7;
    308 	default:       abort();
    309 	}
    310 }
    311 
    312 void
    313 dir(Op *op, Node **args)
    314 {
    315 	Node *imm;
    316 	unsigned char buf[4];
    317 	unsigned val;
    318 	int n = op->size;
    319 
    320 	imm = (args[1]->addr == ADIRECT) ? args[1] : args[0];
    321 	imm = imm->left;
    322 	memcpy(buf, op->bytes, n);
    323 	val = imm->sym->value;
    324 	buf[n-1] = val >> 8;
    325 	buf[n-2] = val;
    326 	emit(buf, n);
    327 }
    328 
    329 void
    330 ld8(Op *op, Node **args)
    331 {
    332 	Node *par1 = args[0], *par2 = args[1];
    333 	int n = op->size, i = n;;
    334 	unsigned regval = 0;
    335 	unsigned char buf[4];
    336 
    337 	memcpy(buf, op->bytes, n);
    338 
    339 	if (par1->addr == AREG)
    340 		regval |= reg2int(par1) << 3;
    341 	if (par2->addr == AREG)
    342 		regval |= reg2int(par2);
    343 	else if (par2->addr == AIMM)
    344 		buf[--i] = par2->sym->value;
    345 
    346 	buf[--i] |= regval;
    347 	emit(buf, n);
    348 }
    349 
    350 void
    351 alu16(Op *op, Node **args)
    352 {
    353 	Node *par;
    354 	int n = op->size;
    355 	unsigned val;
    356 	unsigned char buf[4];
    357 
    358 	par = (args[1]) ? args[1] : args[0];
    359 	val = reg2int(par);
    360 	memcpy(buf, op->bytes, n);
    361 	buf[n-1] |= val << 4;
    362 	emit(buf, n);
    363 }
    364 
    365 void
    366 ld16(Op *op, Node **args)
    367 {
    368 	Node *dst, *src, *tmp;
    369 	int n = op->size;
    370 	unsigned val;
    371 	unsigned char buf[4];
    372 
    373 	dst = args[0];
    374 	src = args[1];
    375 	if (!src) {
    376 		alu16(op, args);
    377 		return;
    378 	}
    379 
    380 	if (dst->addr != AREG) {
    381 		tmp = src;
    382 		src = dst;
    383 		dst = tmp;
    384 	}
    385 
    386 	memcpy(buf, op->bytes, n);
    387 	if (src->addr == ADIRECT)
    388 		src = src->left;
    389 	val = src->sym->value;
    390 	buf[n-1] = val >> 8;
    391 	buf[n-2] = val;
    392 	buf[n-3] |= reg2int(dst) << 4;
    393 	emit(buf, n);
    394 }
    395 
    396 void
    397 alu8(Op *op, Node **args)
    398 {
    399 	Node *par = args[1];
    400 	unsigned char buf[4];
    401 	int n = op->size, shift;
    402 	unsigned val;
    403 
    404 	if (args[1]) {
    405 		shift = 0;
    406 		par = args[1];
    407 	} else {
    408 		shift = 3;
    409 		par = args[0];
    410 	}
    411 
    412 	switch (par->addr) {
    413 	case AIMM:
    414 		val = par->sym->value;
    415 		break;
    416 	case AREG:
    417 		val = reg2int(par) << shift;
    418 		break;
    419 	case AINDEX:
    420 		val = par->left->right->sym->value;
    421 		break;
    422 	case AINDIR:
    423 		val = 0;
    424 		break;
    425 	default:
    426 		abort();
    427 	}
    428 
    429 	memcpy(buf, op->bytes, n);
    430 	buf[n-1] |= val;
    431 	emit(buf, n);
    432 }
    433 
    434 void
    435 idx(Op *op, Node **args)
    436 {
    437 	Node *tmp, *idx, *imm, *reg;
    438 	unsigned char buf[4];
    439 	int n = op->size, i = n, shift = 0;
    440 
    441 	imm = reg = NULL;
    442 	if (args[0]->addr != AINDEX) {
    443 		shift = 3;
    444 		tmp = args[0];
    445 		args[0] = args[1];
    446 		args[1] = tmp;
    447 	}
    448 	idx = args[0]->left->right;
    449 
    450 	if (args[1]->addr == AREG)
    451 		reg = args[1];
    452 	else
    453 		imm = args[1];
    454 
    455 	memcpy(buf, op->bytes, n);
    456 
    457 	if (imm)
    458 		buf[--i] = imm->sym->value;
    459 	buf[--i] = idx->sym->value;
    460 	if (reg)
    461 		buf[--i] |= reg2int(reg) << shift;
    462 
    463 	emit(buf, n);
    464 }
    465 
    466 void
    467 inout(Op *op, Node **args)
    468 {
    469 	Node *port, *value;
    470 	unsigned val;
    471 	int n = op->size;
    472 	unsigned char buf[5];
    473 
    474 	port = args[0];
    475 	value = args[1];
    476 	if (port->addr != ADIRECT && port->addr != AINDIR) {
    477 		value = port;
    478 		port = args[1];
    479 	}
    480 
    481 	if (port->addr == ADIRECT)
    482 		val = port->left->sym->value;
    483 	else if (value->addr == AREG)
    484 		val = reg2int(value) << 3;
    485 	else
    486 		val = 0;
    487 
    488 	memcpy(buf, op->bytes, n);
    489 	buf[n-1] |= val;
    490 	emit(buf, n);
    491 }
    492 
    493 void
    494 rot_bit(Op *op, Node **args)
    495 {
    496 	Node *par = args[0];
    497 	unsigned char buf[5];
    498 	int n = op->size;
    499 	unsigned val, npar = 0;
    500 
    501 	memcpy(buf, op->bytes, n);
    502 
    503 	par = args[0];
    504 	if (par->addr == AIMM) {
    505 		buf[n-1] |= par->sym->value << 3;
    506 		par = args[npar = 1];
    507 	}
    508 
    509 	switch (par->addr) {
    510 	case AINDEX:
    511 		val = par->left->right->sym->value;
    512 		buf[n-2] = val;
    513 		par = args[npar+1];
    514 		if (!par)
    515 			break;
    516 	case AREG:
    517 		val = reg2int(par);
    518 		buf[n-1] |= val;
    519 	case AINDIR:
    520 		break;
    521 	default:
    522 		abort();
    523 	}
    524 
    525 	emit(buf, n);
    526 }
    527 
    528 void
    529 im(Op *op, Node **args)
    530 {
    531 	unsigned val = args[0]->sym->value;
    532 	unsigned char buf[4];
    533 	int n = op->size;
    534 
    535 	if (val > 0)
    536 		++val;
    537 
    538 	memcpy(buf, op->bytes, n);
    539 	buf[n-1] |= val << 3;
    540 	emit(buf, n);
    541 }
    542 
    543 void
    544 branch(int relative, Op *op, Node **args)
    545 {
    546 	unsigned char buf[4];
    547 	Node *flag, *imm;
    548 	int n = op->size, i = n;
    549 	unsigned val;
    550 	int (*fun)(Node *);
    551 
    552 	flag = imm = NULL;
    553 	if (args[0]->addr == AREG) {
    554 		flag = args[0];
    555 		imm = args[1];
    556 	} else if (args[0]->addr == AIMM) {
    557 		imm = args[0];
    558 	}
    559 	memcpy(buf, op->bytes, n);
    560 
    561 	if (imm) {
    562 		val = imm->sym->value;
    563 		if (!relative)
    564 			buf[--i] = val >> 8;
    565 		else
    566 			val -= cursec->curpc - 2;
    567 		buf[--i] = val;
    568 
    569 	}
    570 	if (flag) {
    571 		fun = (relative) ? ss2int : cc2int;
    572 		buf[--i] |= (*fun)(flag) << 3;
    573 	}
    574 
    575 
    576 	emit(buf, n);
    577 }
    578 
    579 void
    580 jp(Op *op, Node **args)
    581 {
    582 	branch(0, op, args);
    583 }
    584 
    585 void
    586 jr(Op *op, Node **args)
    587 {
    588 	branch(1, op, args);
    589 }
    590 
    591 void
    592 rst(Op *op, Node **args)
    593 {
    594 	unsigned char buf[1];
    595 
    596 	buf[0] = op->bytes[0];
    597 	buf[0] |= args[0]->sym->value;
    598 	emit(buf, 1);
    599 }