scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  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
 17static int
 18getclass(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
 67int
 68match(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 */
218Node *
219moperand(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
262static int
263reg2int(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
289static int
290cc2int(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
305static int
306ss2int(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
317void
318dir(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
334void
335ld8(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
355void
356alu16(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
370void
371ld16(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
401void
402alu8(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
439void
440idx(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
471void
472inout(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
498void
499rot_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
533void
534im(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
548void
549branch(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
584void
585jp(Op *op, Node **args)
586{
587	branch(0, op, args);
588}
589
590void
591jr(Op *op, Node **args)
592{
593	branch(1, op, args);
594}
595
596void
597rst(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}