scc

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

ins.c (9687B)


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