/* avrmch.c */

/*
 * (C) Copyright 2003
 * All Rights Reserved
 *
 * Alan R. Baldwin
 * 721 Berkeley St.
 * Kent, Ohio  44240
 */

#include <stdio.h>
#include <setjmp.h>
#include "asxxxx.h"
#include "avr.h"

static char buff[80];
static int ptype;
static int avr_4k;


#define	OPCODE_ERRORS	(1)

#if 0
/* *****-----*****-----***** */ /* Opcode Error Prototype */
#if OPCODE_ERRORS
	if (ptype &    (AT90S1200|AT90S2313|AT90S2343|AT90S2323|AT90S2333|AT90S4433|
			AT90S4414|AT90S8515|AT90S4434|AT90S8535|AT90C8534|
			ATmega603|ATmega103|ATmega161|ATmega163|
			ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny22|ATtiny28)	) {
		err('o');
	}
#endif
/* *****-----*****-----***** */
#endif


/*
 * Process machine ops.
 */
VOID
machine(mp)
struct mne *mp;
{
	char *str;
	register int c, op, t, t1, v, v1;
	struct expr e, e1;

	clrexpr(&e);
	clrexpr(&e1);

	op = mp->m_valu;
	switch (mp->m_type) {

	case X_PTYPE:
		switch(op) {
		default: op = AT90Sxxxx;
		case AT90Sxxxx: str = "AT90Sxxxx"; break;
		case AT90S1200: str = "AT90S1200"; break;
		case AT90S2313: str = "AT90S2313"; break;
		case AT90S2323: str = "AT90S2323"; break;
		case AT90S2343: str = "AT90S2343"; break;
		case AT90S2333: str = "AT90S2333"; break;
		case AT90S4433: str = "AT90S4433"; break;
		case AT90S4414: str = "AT90S4414"; break;
		case AT90S4434: str = "AT90S4434"; break;
		case AT90S8515: str = "AT90S8515"; break;
		case AT90C8534:	str = "AT90C8534"; break;
		case AT90S8535: str = "AT90S8535"; break;
		case ATmega103: str = "ATmega103"; break;
		case ATmega603: str = "ATmega603"; break;
		case ATmega161:	str = "ATmega161"; break;
		case ATmega163:	str = "ATmega163"; break;
		case ATtiny10:  str = "ATtiny10";  break;
		case ATtiny11:  str = "ATtiny11";  break;
		case ATtiny12:  str = "ATtiny12";  break;
		case ATtiny15:  str = "ATtiny15";  break;
		case ATtiny22:  str = "ATtiny22";  break;
		case ATtiny28:  str = "ATtiny28";  break;
		}
		ptype = op;
		sprintf(buff, "%s %s", ATMEL_CPU, str);
		cpu = buff;
		lmode = SLIST;
		break;

	case S_4K:
		expr(&e, 0);
		if (is_abs(&e)) {
			avr_4k = e.e_addr;
		} else {
			err('o');
		}
		lmode = SLIST;
		break;

	case S_BITS:
		if (ptype) {
			err('o');
			break;
		}
		exprmasks(mp->m_valu);
		lmode = SLIST;
		break;

	case S_INH:

#if OPCODE_ERRORS
		if (op == 0x9409) {	/* ijmp */
			if (ptype &    (AT90S1200|
					ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny28)	) {
				err('o');
			}
		}
#endif

#if OPCODE_ERRORS
		if (op == 0x9419) {	/* eijmp */
			if (ptype &    (AT90S1200|AT90S2313|AT90S2343|AT90S2323|AT90S2333|AT90S4433|
					AT90S4414|AT90S8515|AT90S4434|AT90S8535|AT90C8534|
					ATmega603|ATmega103|ATmega161|ATmega163|
					ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny22|ATtiny28)	) {
				err('o');
			}
		}
#endif

#if OPCODE_ERRORS
		if (op == 0x9509) {	/* icall */
			if (ptype &    (AT90S1200|
					ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny28)	) {
				err('o');
			}
		}
#endif

#if OPCODE_ERRORS
		if (op == 0x9519) {	/* eicall */
			if (ptype &    (AT90S1200|AT90S2313|AT90S2343|AT90S2323|AT90S2333|AT90S4433|
					AT90S4414|AT90S8515|AT90S4434|AT90S8535|AT90C8534|
					ATmega603|ATmega103|ATmega163|
					ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny22|ATtiny28)	) {
				err('o');
			}
		}
#endif

#if OPCODE_ERRORS
		if (op == 0x95E8) {	/* spm */
			if (ptype &    (AT90S1200|AT90S2313|AT90S2343|AT90S2323|AT90S2333|AT90S4433|
					AT90S4414|AT90S8515|AT90S4434|AT90S8535|AT90C8534|
					ATmega603|ATmega103|
					ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny22|ATtiny28)	) {
				err('o');
			}
		}
#endif

		outaw(op);
		break;

	case S_IBYTE:	/* Rd,#imm  /  16 <= Rd <= 31, # */
		/*
		 * The addressing mode can be S_REG
		 * or any constant from 16 to 31.
		 */
		t = addr(&e);
		if (!is_abs(&e) || (e.e_addr < 16) || (e.e_addr > 31)) {
			aerr();
		}
		comma();
		t1 = addr(&e1);
		if (is_abs(&e1)) {
			if (e1.e_addr > 255)
				aerr();
		} else
		if ((t1 != S_IMMED) && (t1 != S_EXT)) {
			aerr();
		}
		outrwm(&e1, M_IBYTE, op | ((e.e_addr & 0x0F) << 4));
		break;

	case S_CBR:	/* cbr  Rd,#imm  /  16 <= Rd <= 31, # */
		/*
		 * The addressing mode can be S_REG
		 * or any constant from 16 to 31.
		 */
		t = addr(&e);
		if (!is_abs(&e) || (e.e_addr < 16) || (e.e_addr > 31)) {
			aerr();
		}
		comma();
		t1 = addr(&e1);
		if (is_abs(&e1)) {
			if (e1.e_addr > 255)
				aerr();
		} else {
			aerr();
		}
		v1 = ((~e1.e_addr & 0xF0) << 4) + (~e1.e_addr & 0xF);
		outaw(op | ((e.e_addr & 0x0F) << 4) | v1);
		break;

	case S_IWORD:	/* Rd,#imm  /  Rd == R24,R26,R28,R30, # */

#if OPCODE_ERRORS
		if (ptype &    (AT90S1200|
				ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny28)	) {
			err('o');
		}
#endif

		/*
		 * The addressing mode can be S_REG
		 * or any constant from 24 to 30.
		 */
		t = addr(&e);
		if (!is_abs(&e) || ((e.e_addr & 0x19) != 0x18)) {
			aerr();
		}
		comma();
		t1 = addr(&e1);
		if (is_abs(&e1)) {
			if (e1.e_addr > 63)
				aerr();
		} else
		if ((t1 != S_IMMED) && (t1 != S_EXT)) {
			aerr();
		}
		outrwm(&e1, R_MBRO | M_IWORD, op | ((e.e_addr & 0x06) << 3));
		break;

	case S_SNGL:	/* Rd  /  0 <= Rd <= 31 */

#if OPCODE_ERRORS
		if ((op == 0x900F) || (op == 0x920F)) {		/* pop, push */
			if (ptype &    (AT90S1200|
					ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny28)	) {
				err('o');
			}
		}
#endif

		/*
		 * The addressing mode can be S_REG
		 * or any constant from 0 to 31.
		 */
		t = addr(&e);
		if (!is_abs(&e) ||  (e.e_addr > 31)) {
			aerr();
		}
		outaw(op | ((e.e_addr & 0x1F) << 4));
		break;

	case S_SAME:	/* Rd  /  0 <= Rd <= 31 */
		/*
		 * The addressing mode can be S_REG
		 * or any constant from 0 to 31.
		 */
		t = addr(&e);
		if (!is_abs(&e) ||  (e.e_addr > 31)) {
			aerr();
		}
		outaw(op | ((e.e_addr & 0x1F) << 4) | ((e.e_addr & 0x10) << 5) | (e.e_addr & 0x0F));
		break;

	case S_DUBL:	/* Rd,Rr  /  0 <= Rd,Rr <= 31 */
		/*
		 * The addressing mode can be S_REG
		 * or any constant from 0 to 31.
		 */
		t = addr(&e);
		if (!is_abs(&e) ||  (e.e_addr > 31)) {
			aerr();
		}
		comma();
		t1 = addr(&e1);
		if (!is_abs(&e1) ||  (e1.e_addr > 31)) {
			aerr();
		}
		outaw(op | ((e.e_addr & 0x1F) << 4) | ((e1.e_addr & 0x10) << 5) | (e1.e_addr & 0x0F));
		break;

	case S_MOVW:	/* Rd,Rr  /  0,2,... <= Rd,Rr <= ...,28,30 */

#if OPCODE_ERRORS
		if (ptype &    (AT90S1200|AT90S2313|AT90S2343|AT90S2323|AT90S2333|AT90S4433|
				AT90S4414|AT90S8515|AT90S4434|AT90S8535|AT90C8534|
				ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny22|ATtiny28)	) {
			err('o');
		}
#endif

		/*
		 * The addressing mode can be S_REG
		 * or any constant from 0 to 31.
		 */
		t = addr(&e);
		if (!is_abs(&e) || (e.e_addr > 31) || (e.e_addr & 0x01)) {
			aerr();
		}
		comma();
		t1 = addr(&e1);
		if (!is_abs(&e1) || (e1.e_addr > 31) || (e1.e_addr & 0x01)) {
			aerr();
		}
		outaw(op | (((e.e_addr >> 1) & 0x0F) << 4) | ((e1.e_addr >> 1) & 0x0F));
		break;

	/*
	 * mul
	 */
	case S_MUL:	/* Rd,Rr  /  0 <= Rd,Rr <= 31 */

#if OPCODE_ERRORS
		if (ptype &    (AT90S1200|AT90S2313|AT90S2343|AT90S2323|AT90S2333|AT90S4433|
				AT90S4414|AT90S8515|AT90S4434|AT90S8535|AT90C8534|
				ATmega603|ATmega103|
				ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny22|ATtiny28)	) {
			err('o');
		}
#endif

		/*
		 * The addressing mode can be S_REG
		 * or any constant from 0 to 31.
		 */
		t = addr(&e);
		if (!is_abs(&e) ||  (e.e_addr > 31)) {
			aerr();
		}
		comma();
		t1 = addr(&e1);
		if (!is_abs(&e1) ||  (e1.e_addr > 31)) {
			aerr();
		}
		outaw(op | ((e.e_addr & 0x1F) << 4) | ((e1.e_addr & 0x10) << 5) | (e1.e_addr & 0x0F));
		break;

	/*
	 * muls
	 */
	case S_MULS:	/* Rd,Rr  /  16 <= Rd,Rr <= 31 */

#if OPCODE_ERRORS
		if (ptype &    (AT90S1200|AT90S2313|AT90S2343|AT90S2323|AT90S2333|AT90S4433|
				AT90S4414|AT90S8515|AT90S4434|AT90S8535|AT90C8534|
				ATmega603|ATmega103|
				ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny22|ATtiny28)	) {
			err('o');
		}
#endif

		/*
		 * The addressing mode can be S_REG
		 * or any constant from 16 to 31.
		 */
		t = addr(&e);
		if (!is_abs(&e) || (e.e_addr < 16) || (e.e_addr > 31)) {
			aerr();
		}
		comma();
		t1 = addr(&e1);
		if (!is_abs(&e1) || (e1.e_addr < 16) || (e1.e_addr > 31)) {
			aerr();
		}
		outaw(op | ((e.e_addr & 0x0F) << 4) | (e1.e_addr & 0x0F));
		break;

	/*
	 * mulsu
	 * fmul
	 * fmuls
	 * fmulsu
	 */
	case S_FMUL:	/* Rd,Rr  /  16 <= Rd,Rr <= 23 */

#if OPCODE_ERRORS
		if (ptype &    (AT90S1200|AT90S2313|AT90S2343|AT90S2323|AT90S2333|AT90S4433|
				AT90S4414|AT90S8515|AT90S4434|AT90S8535|AT90C8534|
				ATmega603|ATmega103|
				ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny22|ATtiny28)	) {
			err('o');
		}
#endif

		/*
		 * The addressing mode can be S_REG
		 * or any constant from 16 to 23.
		 */
		t = addr(&e);
		if (!is_abs(&e) || (e.e_addr < 16) || (e.e_addr > 23)) {
			aerr();
		}
		comma();
		t1 = addr(&e1);
		if (!is_abs(&e1) || (e1.e_addr < 16) || (e1.e_addr > 23)) {
			aerr();
		}
		outaw(op | ((e.e_addr & 0x07) << 4) | (e1.e_addr & 0x07));
		break;

	case S_SER:	/* Rd  /  16 <= Rd <= 31 */
		/*
		 * The addressing mode can be S_REG
		 * or any constant from 16 to 31.
		 */
		t = addr(&e);
		if (!is_abs(&e) || (e.e_addr < 16) || (e.e_addr > 31)) {
			aerr();
		}
		outaw(op | ((e.e_addr & 0xF) << 4));
		break;

	case S_SREG:	/* Bit Number  /  b <= 7 */
		t = addr(&e);
		abscheck(&e);
		if (e.e_addr > 7)
			aerr();
		outaw(op | ((e.e_addr & 0x07) << 4));
		break;

	case S_SKIP:
	case S_TFLG:	/* Rd,b  /  0 <= Rd <= 31, b <= 7 */
		/*
		 * The addressing mode can be S_REG
		 * or any constant from 0 to 31.
		 */
		t = addr(&e);
		if (!is_abs(&e) ||  (e.e_addr > 31)) {
			aerr();
		}
		comma();
		expr(&e1, 0);
		abscheck(&e1);
		if (e1.e_addr > 7)
			aerr();
		outaw(op | ((e.e_addr & 0x1F) << 4) | (e1.e_addr & 7));
		break;

	case S_BRA:	/* BR__  label */
		/* Relative branch */
		expr(&e, 0);
		if (mchpcr(&e)) {
			v = e.e_addr - dot.s_addr - 1;
			if ((v < -64) || (v > 63))
				aerr();
			outaw(op | ((v & 0x7F) << 3));
		} else {
			outrwm(&e, R_PCR | M_BRA, op);
		}
		if (e.e_mode != S_USER)
			rerr();
		break;

	case S_SBRA:	/* BR__  b,label  /  b <= 7 */
		/* Relative branch */
		expr(&e, 0);
		abscheck(&e);
		if (e.e_addr > 7)
			aerr();
		comma();
		expr(&e1, 0);
		if (mchpcr(&e1)) {
			v = e1.e_addr - dot.s_addr - 1;
			if ((v < -64) || (v > 63))
				aerr();
			outaw(op | ((v & 0x7F) << 3) | (e.e_addr & 0x07));
		} else {
			outrwm(&e1, R_PCR | M_BRA, op | (e.e_addr & 0x07));
		}
		if (e1.e_mode != S_USER)
			rerr();
		break;

	case S_JMP:	/* label */

#if OPCODE_ERRORS
		if (ptype &    (AT90S1200|AT90S2313|AT90S2343|AT90S2323|AT90S2333|AT90S4433|
				AT90S4414|AT90S8515|AT90S4434|AT90S8535|AT90C8534|
				ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny22|ATtiny28)	) {
			err('o');
		}
#endif

		expr(&e, 0);
		outr4bm(&e, R_MBRO | M_JMP, op);
		break;

	case S_RJMP:	/* label */
		expr(&e, 0);
		if (mchpcr(&e)) {
			v = e.e_addr - dot.s_addr - 1;
			if (avr_4k == 0)
				if ((v < -2048) || (v > 2047))
					aerr();
			outaw(op | (v & 0x0FFF));
		} else {
			outrwm(&e, (avr_4k ? R_PCRN : R_PCR) | M_RJMP, op);
		}
		if (e.e_mode != S_USER)
			rerr();
		break;


	case S_IOR:	/* P,b  /  0 <= P <= 31,  b <= 7 */
		t = addr(&e);
		if (is_abs(&e)) {
			if (e.e_addr > 31)
				aerr();
		} else
		if ((t != S_IMMED) && (t != S_EXT)) {
			aerr();
		}
		comma();
		expr(&e1, 0);
		abscheck(&e1);
		if (e1.e_addr > 7)
			aerr();
		outrwm(&e, R_MBRO | M_IOR, op | (e1.e_addr & 7));
		break;

	case S_IN:	/* Rd,P  /  0 <= Rd <= 31,  0 <= P <= 63 */
		/*
		 * The addressing mode can be S_REG
		 * or any constant from 0 to 31.
		 */
		t = addr(&e);
		if (!is_abs(&e) ||  (e.e_addr > 31)) {
			aerr();
		}
		comma();
		t1 = addr(&e1);
		if (is_abs(&e1)) {
			if (e1.e_addr > 63)
				aerr();
		} else
		if ((t1 != S_IMMED) && (t1 != S_EXT)) {
			aerr();
		}
		outrwm(&e1, R_MBRO | M_IOP, op | ((e.e_addr & 0x1F) << 4));
		break;

	case S_OUT:	/* P,Rd  /  0 <= Rd <= 31,  0 <= P <= 63 */
		t = addr(&e);
		if (is_abs(&e)) {
			if (e.e_addr > 63)
				aerr();
		} else
		if ((t != S_IMMED) && (t != S_EXT)) {
			aerr();
		}
		comma();
		/*
		 * The addressing mode can be S_REG
		 * or any constant from 0 to 31.
		 */
		t1 = addr(&e1);
		if (!is_abs(&e1) ||  (e1.e_addr > 31)) {
			aerr();
		}
		outrwm(&e, R_MBRO | M_IOP, op | ((e1.e_addr & 0x1F) << 4));
		break;

	case S_LD:	/* Rd,X */
		/*
		 * The addressing mode can be S_REG
		 * or any constant from 0 to 31.
		 */
		t = addr(&e);
		if (!is_abs(&e) || (e.e_addr > 31)) {
			aerr();
		}
		comma();
		t1 = addr(&e1);
		if (t1 != S_IND)
			aerr();

#if OPCODE_ERRORS
		if (e1.e_addr) {	/* != Rd,Z */
			if (ptype &    (AT90S1200|
					ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny28)	) {
				err('o');
			}
		}
#endif

		outaw(op | e1.e_addr | ((e.e_addr & 0x1F) << 4));
		break;

	case S_ST:	/* X,Rd */
		t = addr(&e);
		if (t != S_IND)
			aerr();

#if OPCODE_ERRORS
		if (e.e_addr) {		/* != Rd,Z */
			if (ptype &    (AT90S1200|
					ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny28)	) {
				err('o');
			}
		}
#endif

		comma();
		/*
		 * The addressing mode can be S_REG
		 * or any constant from 0 to 31.
		 */
		t1 = addr(&e1);
		if (!is_abs(&e1) || (e1.e_addr > 31)) {
			aerr();
		}
		outaw(op | e.e_addr | ((e1.e_addr & 0x1F) << 4));
		break;

	case S_ILD:	/* Rd,Y+Q  /  0 <= Rd <= 31, 0 <= Q <= 63 */

#if OPCODE_ERRORS
		if (ptype &    (AT90S1200|
				ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny28)	) {
			err('o');
		}
#endif

		/*
		 * The addressing mode can be S_REG
		 * or any constant from 0 to 31.
		 */
		t = addr(&e);
		if (!is_abs(&e) || (e.e_addr > 31)) {
			aerr();
		}
		comma();
		c = getnb();
		if (getnb() != '+')
			qerr();
		t1 = addr(&e1);
		if (is_abs(&e1)) {
			if (e1.e_addr > 63)
				aerr();
		} else
		if ((t1 != S_IMMED) && (t1 != S_EXT)) {
			aerr();
		}
		switch(ccase[c & 0x7F]) {
		default:
		case 'x':
			aerr();
			outaw(0);
			break;
		case 'y':
			op |= 0x08;
		case 'z':
			outrwm(&e1, R_MBRO | M_ILDST, op | ((e.e_addr & 0x1F) << 4));
			break;
		}
		break;

	case S_IST:	/* Y+Q,Rd  /  0 <= Rd <= 31, 0 <= Q <= 63 */

#if OPCODE_ERRORS
		if (ptype &    (AT90S1200|
				ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny28)	) {
			err('o');
		}
#endif

		c = getnb();
		if (getnb() != '+')
			qerr();
		t = addr(&e);
		if (is_abs(&e)) {
			if (e.e_addr > 63)
				aerr();
		} else
		if ((t != S_IMMED) && (t != S_EXT)) {
			aerr();
		}
		comma();
		/*
		 * The addressing mode can be S_REG
		 * or any constant from 0 to 31.
		 */
		t1 = addr(&e1);
		if (!is_abs(&e1) ||  (e1.e_addr > 31)) {
			aerr();
		}
		switch(ccase[c & 0x7F]) {
		default:
		case 'x':
			aerr();
			outaw(0);
			break;
		case 'y':
			op |= 0x08;
		case 'z':
			outrwm(&e, R_MBRO | M_ILDST, op | ((e1.e_addr & 0x1F) << 4));
			break;
		}
		break;

	case S_LDS:	/* Rd,label  /  0 <= Rd <= 31 */

#if OPCODE_ERRORS
		if (ptype &    (AT90S1200|
				ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny28)	) {
			err('o');
		}
#endif

		/*
		 * The addressing mode can be S_REG
		 * or any constant from 0 to 31.
		 */
		t = addr(&e);
		if (!is_abs(&e) ||  (e.e_addr > 31)) {
			aerr();
		}
		comma();
		t1 = addr(&e1);
		if (t1 != S_EXT)
			aerr();
		outaw(op | ((e.e_addr & 0x1F) << 4));
		outrw(&e1, R_NORM);
		break;

	case S_STS:	/* label,Rd  /  0 <= Rd <= 31 */

#if OPCODE_ERRORS
		if (ptype &    (AT90S1200|
				ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny28)	) {
			err('o');
		}
#endif

		t = addr(&e);
		if (t != S_EXT)
			aerr();
		comma();
		/*
		 * The addressing mode can be S_REG
		 * or any constant from 0 to 31.
		 */
		t1 = addr(&e1);
		if (!is_abs(&e1) ||  (e1.e_addr > 31)) {
			aerr();
		}
		outaw(op | ((e1.e_addr & 0x1F) << 4));
		outrw(&e, R_NORM);
		break;

	case S_LPM:	/* blank, Rd,z, or Rd,z+  /  0 <= Rd <= 31 */
		if (more()) {

#if OPCODE_ERRORS
			if (ptype &    (AT90S1200|AT90S2313|AT90S2343|AT90S2323|AT90S2333|AT90S4433|
					AT90S4414|AT90S8515|AT90S4434|AT90S8535|AT90C8534|
					ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny22|ATtiny28)	) {
				err('o');
			}
#endif

			/*
			 * The addressing mode can be S_REG
			 * or any constant from 0 to 31.
			 */
			t = addr(&e);
			if (!is_abs(&e) ||  (e.e_addr > 31)) {
				aerr();
			}
			comma();
			t1 = addr(&e1);
			if (t1 != S_IND)
				aerr();
			if (e1.e_addr == 0x0000) {	/* Rd,z  */
				outaw(0x9004 | ((e.e_addr & 0x1F) << 4));
			} else
			if (e1.e_addr == 0x1001) {	/* Rd,z+ */
				outaw(0x9005 | ((e.e_addr & 0x1F) << 4));
			} else {
				outaw(op);
				aerr();
			}
		} else {				/* blank */

#if OPCODE_ERRORS
			if (ptype &    (AT90S1200|
					ATtiny10|ATtiny11|ATtiny12)	) {
				err('o');
			}
#endif

			outaw(op);
		}
		break;

	case S_ELPM:	/* blank, Rd,z, or Rd,z+  /  0 <= Rd <= 31 */
		if (more()) {

#if OPCODE_ERRORS
		if (ptype &    (AT90S1200|AT90S2313|AT90S2343|AT90S2323|AT90S2333|AT90S4433|
				AT90S4414|AT90S8515|AT90S4434|AT90S8535|AT90C8534|
				ATmega603|ATmega103|ATmega161|ATmega163|
				ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny22|ATtiny28)	) {
			err('o');
		}
#endif

			/*
			 * The addressing mode can be S_REG
			 * or any constant from 0 to 31.
			 */
			t = addr(&e);
			if (!is_abs(&e) ||  (e.e_addr > 31)) {
				aerr();
			}
			comma();
			t1 = addr(&e1);
			if (t1 != S_IND)
				aerr();
			if (e1.e_addr == 0) {		/* Rd,z  */
				outaw(0x9006 | ((e.e_addr & 0x1F) << 4));
			} else
			if (e1.e_addr == 0x1001) {	/* Rd,z+ */
				outaw(0x9007 | ((e.e_addr & 0x1F) << 4));
			} else {
				outaw(op);
				aerr();
			}
		} else {				/* blank */

#if OPCODE_ERRORS
			if (ptype &    (AT90S1200|AT90S2313|AT90S2343|AT90S2323|AT90S2333|AT90S4433|
					AT90S4414|AT90S8515|AT90S4434|AT90S8535|AT90C8534|
					ATmega603|ATmega103|ATmega163|
					ATtiny10|ATtiny11|ATtiny12|ATtiny15|ATtiny22|ATtiny28)	) {
				err('o');
			}
#endif

			outaw(op);
		}
		break;

	default:
		err('o');
	}
}

/*
 * Branch/Jump PCR Mode Check
 */
int
mchpcr(esp)
register struct expr *esp;
{
	if (esp->e_base.e_ap == dot.s_area) {
		return(1);
	}
	if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
		/*
		 * Absolute Destination
		 *
		 * Use the global symbol '.__.ABS.'
		 * of value zero and force the assembler
		 * to use this absolute constant as the
		 * base value for the relocation.
		 */
		esp->e_flag = 1;
		esp->e_base.e_sp = &sym[1];
	}
	return(0);
}

/*
 * Is the next character a comma ?
 */
int
comma()
{
	if (getnb() != ',')
		qerr();
	return(1);
}

/*
 * Machine specific initialization
 */

VOID
minit()
{
	exprmasks(4);
	avr_4k = 0;
}

