diff options
Diffstat (limited to 'assemble.c')
| -rw-r--r-- | assemble.c | 587 | 
1 files changed, 484 insertions, 103 deletions
@@ -82,6 +82,21 @@ uint8_t get_eind(uint8_t mne, uint8_t dbg) {  	return 0xFF;  } +uint8_t get_ext_ortho(uint8_t mne, uint8_t dbg) { +	switch (mne) { +		case LEA: return OP_LEA; +		case PEA: return OP_PEA; +		case ADD: return OP_ADD; +		case SUB: return OP_SUB; +		case NOT: return OP_NOT; +		case CLZ: return OP_CLZ; +		case CLO: return OP_CLO; +		case SWP: return OP_SWP; +		case PCN: return OP_PCN; +	} +	return 0xFF; +} +  static void write_value(uint64_t value, uint64_t address, uint8_t size) {  	if (address < mem_size) {  		size = (size > 7) ? 7 : size; @@ -98,16 +113,23 @@ static void write_value(uint64_t value, uint64_t address, uint8_t size) {  	}  } -uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) { +uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t end_expr, uint8_t stop_comma, uint8_t dbg) {  	uint64_t value = 0;  	uint64_t tmp_val = 0;  	uint8_t type = EXPR_NONE;  	uint8_t isstart = 1; +	int done = 0;  	do {  		if (t->id == TOK_EXPR) {  			type = t->type;  			t = t->next;  		} +		if (stop_comma && t->subtype == TOK_CSV) { +			done = 1; +		} +		if (stop_comma && t->id == TOK_REG) { +			break; +		}  		switch (t->id) {  			case TOK_HEX:  			case TOK_DEC: @@ -119,6 +141,10 @@ uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) {  				tmp_val = (t->sym) ? t->sym->val : addr;  				t = t->next;  				break; +			default: tmp_val = 0; +		} +		if (end_expr != 0xFF && type == end_expr) { +			break;  		}  		switch (type) {  			case EXPR_PLUS : (isstart) ? (value =  tmp_val) : (value += tmp_val); break; @@ -150,13 +176,19 @@ uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) {  		if (dbg) {  			printf("get_val(): Value: $%"PRIX64", Expression type: $%X, Expression Value: $%"PRIX64".\n", value, type, tmp_val);  		} -	} while (t && t->id == TOK_EXPR && isexpr(t->type, dbg)); +	} while (!done && t && t->id == TOK_EXPR && isexpr(t->type, dbg));  	return value;  } -token *skip_expr(token *t, uint8_t dbg) { +token *skip_expr(token *t, uint8_t end_expr, uint8_t stop_comma, uint8_t dbg) { +	int done = 0; +	int is_reg = 0;  	do { -		t = (t->id == TOK_EXPR) ? t->next : t; +		is_reg = (t && t->next && t->next->id == TOK_REG); +		t = (t->id == TOK_EXPR && !is_reg) ? t->next : t; +		if (is_reg || (stop_comma && (t->subtype == TOK_CSV))) { +			done = 1; +		}  		switch (t->id) {  			case TOK_HEX  :  			case TOK_DEC  : @@ -165,7 +197,10 @@ token *skip_expr(token *t, uint8_t dbg) {  			case TOK_SYM  :  			case TOK_LABEL: t = t->next; break;  		} -	} while (t && t->id == TOK_EXPR && isexpr(t->type, dbg)); +		if (end_expr != 0xFF && t->id == TOK_EXPR && t->type == end_expr) { +			break; +		} +	} while (!done && t && t->id == TOK_EXPR && isexpr(t->type, dbg));  	return t;  } @@ -227,7 +262,7 @@ uint16_t handle_struct(line **ln, uint64_t address, uint16_t offset, uint8_t dbg  							case DIR_QWORD : member_size = 8; break;  							case DIR_UNION :  							case DIR_STRUCT: member_size = handle_struct(&l, address, offset, dbg); break; -							case DIR_RES   : member_size = get_val(t, address, 3, dbg); t = skip_expr(t, dbg); break; +							case DIR_RES   : member_size = get_val(t, address, 3, 0xFF, 0, dbg); t = skip_expr(t, 0xFF, 0, dbg); break;  						}  						if (member && t->type != DIR_UNION && t->type != DIR_STRUCT) {  							member->val = offset; @@ -270,7 +305,7 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre  			case TOK_CHAR:  			case TOK_SYM:  			case TOK_LABEL: -				val.u64 = get_val(t, tmpaddr, get_directivesize(type, dbg), dbg); +				val.u64 = get_val(t, tmpaddr, get_directivesize(type, dbg), 0xFF, 0, dbg);  				switch (type) {  					case DIR_QWORD: tmp = 8; break;  					case DIR_DWORD: tmp = 4; break; @@ -281,7 +316,7 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre  				tmpaddr += tmp;  				bc->datasize += tmp;  				if (t->next && t->next->id == TOK_EXPR && isexpr(t->next->type, dbg)) { -					t = skip_expr(t, dbg); +					t = skip_expr(t, 0xFF, 0, dbg);  				}  				break;  			case TOK_STRING: @@ -323,9 +358,13 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre  	return tmpaddr;  } -static uint8_t write_inst(uint8_t prefix, uint8_t ext_prefix, uint8_t opcode, uint64_t value, uint64_t address, uint8_t size, uint8_t isasm, uint8_t dbg) { +static uint8_t write_inst(uint8_t prefix, uint8_t ext_prefix, uint8_t opcode, operand *op, uint64_t address, uint8_t *op_size, uint8_t isasm, uint8_t dbg) {  	uint8_t inst_size = 0; +	uint8_t op_ins_size[2];  	union reg ins; +	union reg op_ins[2]; +	memset(op_ins_size, 0, sizeof(op_ins_size)); +	memset(op_ins, 0, sizeof(op_ins_size));  	if (prefix & 3) {  		ins.u8[inst_size++] = prefix;  	} @@ -333,16 +372,216 @@ static uint8_t write_inst(uint8_t prefix, uint8_t ext_prefix, uint8_t opcode, ui  		ins.u8[inst_size++] = ext_prefix;  	}  	ins.u8[inst_size++] = opcode; +	if (ext_prefix == 0x1D) { +		for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { +			ins.u8[inst_size] |= (op[i].id << (!i*4)); +		} +		inst_size++; +		for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { +			int is_sib = 0; +			if (op[i].type == 1) { +				int reg = 0; +				switch (op[i].id) { +					case MEM_SIB  : op_ins[i].u8[op_ins_size[i]++] = op[i].scale; /* Falls through. */ +					case MEM_ABSR : +					case MEM_ARIND: +					case MEM_AINDR: +					case MEM_ZMR  : +					case MEM_ZRIND: +					case MEM_ZINDR: +					case MEM_RIND : +						op_ins[i].u8[op_ins_size[i]] = op[i].rind[reg]; +						reg = (op[i].rind[1] != 0xFF); +						op_ins[i].u8[op_ins_size[i]++] |= op[i].rind[reg] << 4; +						break; +				} +			} +		} +	}  	if (isasm) { +		if (dbg) { +			printf("$%04"PRIX64":\t", address); +			for (int i = 0; i < inst_size; i++) { +				printf("%02X", ins.u8[i]); +				if (i < inst_size-1) { +					putchar(' '); +				} +			} +		}  		write_value(ins.u64, address, inst_size-1); -		if (size) { -			write_value(value, address+inst_size, size-1); +	} +	for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { +		if (op[i].type == 1) { +			if (ext_prefix == 0x1D && op_ins_size[i]) { +				if (isasm) { +					if (dbg) { +						putchar(' '); +						for (int j = 0; j < op_ins_size[i]; j++) { +							printf("%02X", op_ins[i].u8[j]); +							if (j < op_ins_size[i]-1) { +								putchar(' '); +							} +						} +					} +					write_value(op_ins[i].u64, address+inst_size, op_ins_size[i]-1); +				} +				inst_size += op_ins_size[i]; +			} +			if (op_size[i] && (ext_prefix != 0x1D || (ext_prefix == 0x1D && op[i].id != MEM_SIB && op[i].id != MEM_RIND))) { +				if (isasm) { +					if (dbg) { +						uint8_t *tmp = (uint8_t *)&op[i].value; +						putchar(' '); +						for (int j = 0; j < op_size[i]; j++) { +							printf("%02X", tmp[j]); +							if (j < op_size[i]-1) { +								putchar(' '); +							} +						} +					} +					write_value(op[i].value, address+inst_size, op_size[i]-1); +				} +				inst_size += op_size[i]; +			}  		}  	} -	inst_size += size; +	if (isasm && dbg) { +		putchar('\n'); +	}  	return inst_size;  } +token *get_operands(token *t, operand *op, uint64_t address, uint8_t rs, uint8_t dbg) { +	uint8_t op_type; +	uint8_t op_inst; +	/*switch (t->id) { +		case TOK_OPCODE: +		case TOK_EXTOP : +		case TOK_ORTHO : +			op_type = t->id; +			op_inst = t->byte; +			t = t->next; +			break; +	}*/ +	int i = 0; +	int old_i = -1; +	uint8_t expr_type = 0xFF; +	uint8_t stop_comma = 0; +	uint64_t value = 0; +	uint8_t reg = 0; +	uint8_t got_value = 0; +	uint8_t is_sib = 0; +	uint8_t brack_done = 0; +	uint8_t is_comma = 0; +	token *tmp = t; +	/*for (; tmp; tmp = tmp->next) { +		printf("t: %p, t->id: $%X, t->id: %s, t->subtype: $%X, t->subtype: %s\n", tmp, tmp->id, (tmp->id <= TOK_MEMBER) ? lex_tok[tmp->id] : "TOK_NONE", tmp->subtype, (tmp->subtype == TOK_IND || tmp->subtype == TOK_CSV) ? lex_tok[tmp->subtype] : "TOK_NONE"); +	}*/ + +	for (; t && i < 2; t = t->next) { +		if (t->subtype == TOK_IND) { +			brack_done = 1; +		} +		switch (t->id) { +			case TOK_HEX  : +			case TOK_DEC  : +			case TOK_BIN  : +			case TOK_SYM  : +			case TOK_CHAR : +			case TOK_LABEL: +				if (!got_value) { +					expr_type = (expr_type == 0xFF && t->next && t->next->id == TOK_EXPR) ? t->next->type : expr_type; +					switch (expr_type) { +						default		: stop_comma = 1; break; +						case EXPR_MUL	: stop_comma = 0; break; +					} +					is_sib = (!stop_comma && op[i].type && op[i].id == MEM_IND); +					value = get_val(t, address, (rs != 0xFF) ? rs : 0, (!stop_comma) ? expr_type : 0xFF, stop_comma, dbg); +					op[i].value = (!is_sib) ? value : op[i].value; +					got_value = 1; +				} else { +					op[i].value = (!is_sib) ? value : op[i].value; +					got_value = 0; +				} +				if ((op[i].type == 1 && op[i].id == MEM_RIND) || (!op[i].type)) { +					op[i].is_ind = (op[i].type == 1 && op[i].id == MEM_RIND); +					op[i].type = 1; +					op[i].rind[0] = (op[i].rind[0] == 0xFF) ? op[i].id : op[i].rind[0]; +					op[i].id = MEM_ZMR; +				} +				is_comma += (t && (t->subtype == TOK_CSV || (t->next && t->next->subtype == TOK_CSV))); +				is_comma = (is_comma >= 2) ? 0 : is_comma; +				/* Falls Through. */ +			case TOK_MEM: +				is_comma = (t->id == TOK_MEM) ? 0 : is_comma; +				if (old_i != i) { +					op[i].type = 1;	/* Set type to memory. */ +					op[i].id = (t->id == TOK_MEM) ? t->type : 0xFF; +					op[i].id = (is_sib) ? MEM_SIB : op[i].id; +					op[i].scale = (is_sib) ? value : op[i].scale; +					old_i = i; +				} else { +					if (!op[i].type && !is_sib) { +						op[i].type = 1; +						op[i].id = MEM_ZMR; +					} +				} +				if (got_value && !is_comma) { +					if (t && t->subtype != TOK_CSV) { +						t = skip_expr(t, (!stop_comma) ? expr_type : 0xFF, stop_comma, dbg); +					} +				} +				i += is_comma; +				if (old_i != i) { +					got_value = 0; +				} +				break; +			case TOK_REG: +				if (old_i != i) { +					op[i].type = 0;	/* Set type to register. */ +					op[i].id = t->type; +					old_i = i; +				} else { +					if (op[i].type == 1) { +						if (op[i].id == MEM_IND) { +							op[i].id = (!brack_done && got_value) ? MEM_ZRIND : MEM_RIND; +							op[i].id = (brack_done && got_value) ? MEM_ZINDR : op[i].id; +							brack_done = 0; +						} else { +							op[i].id = (got_value) ? MEM_ZMR : op[i].id; +						} +						op[i].rind[reg] = t->type; +						reg++; +						reg = (reg > 1) ? 0 : reg; +					} +				} +				is_comma += (t && (t->subtype == TOK_CSV || (t->next && t->next->subtype == TOK_CSV))); +				is_comma = (is_comma >= 2) ? 0 : is_comma; +				i += is_comma; +				break; +			case TOK_EXPR: +				expr_type = t->type; +				switch (expr_type) { +					default		: stop_comma = 1; break; +					case EXPR_MUL	: stop_comma = 0; break; +				} +				if (!got_value) { +					if (t->next && t->next->id != TOK_REG) { +						value = get_val(t, address, (rs != 0xFF) ? rs : 0, (!stop_comma) ? expr_type : 0xFF, stop_comma, dbg); +						got_value = 1; +					} +				} else { +					got_value = 0; +				} +				break; +		} +		if (!t) { +			break; +		} +	} +	return t; +} +  uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) {  	union reg val;  	uint8_t opsize; @@ -352,44 +591,66 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,  	uint8_t ext_prefix = 0;  	uint8_t type;  	uint32_t am = 0; -	uint8_t tmp = 0; +	uint8_t op_size[2];  	uint8_t prefix = 0;  	uint8_t rs = 0;  	uint8_t of = 0;  	uint8_t tmp_prefix = 0;  	uint8_t inst_size = 0; +	int is_ortho = 0;  	val.u64 = 0;  	instruction ins; - -	for (; t; t = t->next) { -		if (t->id == TOK_OPCODE || t->id == TOK_EXTOP) { +	operand op[2]; +	memset(op, 0xFF, sizeof(op)); +	op_size[0] = 0; +	op_size[1] = 0; +	if (t) { +		if (t->id == TOK_OPCODE || t->id == TOK_EXTOP || t->id == TOK_ORTHO) {  			id = t->id;  			instr = t->byte;  			type = t->type;  		} else { -			break; +			return address;  		} -		tmp = 0; +		/*tmp = 0;*/  		opsize = 1;  		opcode = 0;  		if (t->next) {  			rs = get_rs(t->next, dbg);  			t = (rs != 0xFF) ? t->next : t;  			if (t->next) { -				of = get_of(t->next, dbg); -				t = (of != 0xFF) ? t->next : t; +				is_ortho = (t->next->id == TOK_OS); +				t = (is_ortho) ? t->next : t; +				if (t->next) { +					of = get_of(t->next, dbg); +					t = (of != 0xFF) ? t->next : t; +				}  			}  		} +		get_operands(t, op, address, rs, dbg); +		if (dbg) { +			for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { +				printf("%i: op.type: %u, op.id: $%X, op.scale; $%X, op.rind[0]: $%X, op.rind[1]: $%X, op.value: $%"PRIX64"\n", i, op[i].type, op[i].id, op[i].scale, op[i].rind[0], op[i].rind[1], op[i].value); +			} +		} +		uint8_t is_eind = (op[0].type == 1 && op[0].id == MEM_RIND && op[0].rind[0] == REG_E); +		uint8_t is_mem = (op[0].type == 1 && op[0].id != MEM_IMM); +		uint8_t is_idx = (is_mem && !op[1].type && (op[1].id == REG_X || op[1].id == REG_Y)); +		of = (is_mem && (op[0].id == MEM_RIND || op[0].id == MEM_ZMR) && op[0].rind[0] == REG_SP) ? 1 : of;  		if (rs != 0xFF || of != 0xFF) {  			tmp_prefix  = (rs != 0xFF) ? (rs << 0) : tmp_prefix;  			tmp_prefix |= (of != 0xFF) ? (of << 2) : tmp_prefix;  		}  		prefix = (tmp_prefix) ? ((tmp_prefix << 4) | 3) : 0;  		uint8_t isincdec = (instr == INC || instr == DEC); -		uint8_t isimplied = ((!t->next || (t->next->id == TOK_COMMENT)) && type == 0xFF); -		ins = (id == TOK_OPCODE) ? inst[instr] : ext_inst[instr]; +		uint8_t isimplied = (op[0].type == 0xFF); +		switch (id) { +			case TOK_OPCODE: ins = 	     inst[instr]; break; +			case TOK_EXTOP : ins =   ext_inst[instr]; break; +			case TOK_ORTHO : ins = ortho_inst[instr]; break; +		}  		am = ins.am; -		if (id == TOK_EXTOP || (id == TOK_OPCODE && type == EIND)) { +		if (id == TOK_EXTOP || (id == TOK_OPCODE && is_eind)) {  			ext_prefix = 0x0D;  		}  		if ((am & AM_IMPL) && isimplied) { @@ -398,12 +659,6 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,  			if (ins.am & AM_REL) {  				type = REL;  			} -			if (t->next) { -				t = t->next; -			} -			if (type != BREG && type != EIND) { -				val.u64 = get_val(t, address, (rs != 0xFF) ? rs : 0, dbg); -			}  		}  		opcode = ins.op;  		uint64_t saveaddr = address; @@ -411,62 +666,73 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,  		uint8_t i = 0;  		uint8_t j = 1;  		uint8_t type2 = 0xFF; -		switch (type) { -			case BREG: -			case IMPL: -			case EIND: -				if (id == TOK_OPCODE && instr == CPS) { -					rs = 0; -				} -				if ((am & (AM_IMPL|AM_BREG|AM_EIND|AM_EIND2))) { -					if ((type == EIND) && (am & AM_EIND|AM_EIND2)) { -						int eind_type = ((am & AM_EIND2) != 0); -						switch (eind_type) { -							case 0: opcode = (id == TOK_EXTOP) ? opcode+0x14 : opcode+0x10; break; -							case 1: opcode = (id == TOK_EXTOP) ? opcode+0x01 : eind_base_ops[get_eind(instr, dbg)]; break; -						} -					} -					opcode = (am & AM_BREG) ? opcode+0x14 : opcode; -				} -				break; -			case REL: -			case IMM: -				if (am & (AM_IMM|AM_REL)) { -					rs = (rs != 0xFF) ? rs : 0; -					tmp = (1 << rs); -					if (type == REL) { -						uint64_t max_sign = 0; -						uint8_t offset = 1; -						uint64_t tmp_val; -						tmp_val = val.u64; -						offset += (prefix != 0); -						tmp_val -= offset+tmp; -						tmp_val -= address; -						switch (rs) { -							default: max_sign = (int8_t )(1 <<  7); break; -							case 1 : max_sign = (int16_t)(1 << 15); break; -							case 2 : max_sign = (int32_t)(1 << 31); break; -							case 3 : max_sign = (int64_t)((uint64_t)1 << 63); break; -						} -						if ((int64_t)tmp_val > ~(int64_t)max_sign || (int64_t)tmp_val < (int64_t)max_sign) { -							offset += (!rs); -							rs += (rs <= 3); -							tmp = (1 << rs); -							tmp_val = val.u64; -							tmp_val -= offset+tmp; -							tmp_val -= address; -							prefix = ((rs << 4) | 3); -						} -						val.u64 = tmp_val; +		if (!is_ortho) { +			is_ortho = (id == TOK_ORTHO); +		} +		int is_valid = 1; +		if (!is_ortho && (is_mem || is_idx)) { +			switch (op[0].id) { +				case MEM_AINDR: +				case MEM_ZINDR: +				case MEM_ARIND: +				case MEM_ZRIND: +				case MEM_SIB  : is_valid = 0; break; +				case MEM_ZMR  : +				case MEM_ABSR : +				case MEM_RIND : +				default       : +					if (is_mem && !op[1].type && op[1].id != REG_X && op[1].id != REG_Y) { +						is_valid = 0; +					} else if (op[0].id == MEM_ZMR || op[0].id == MEM_ABSR || op[0].id == MEM_RIND) { +						is_valid = (of != 0xFF || op[0].rind[0] == REG_SP); +					} else if (is_mem && op[1].type == 1) { +						is_valid = 0;  					} -				} -				break; -			default: +					break; +			} +		} else if (is_ortho) { +			is_valid = 0; +		} +		if (type == IMPL && (am & AM_IMPL)) { +			if (id == TOK_OPCODE && instr == CPS) { +				rs = 0; +			} +			opcode = opcode; +			is_ortho = 0; +		} else if (type == REL) { +			rs = (rs != 0xFF) ? rs : 0; +			op_size[0] = (1 << rs); +			uint64_t max_sign = 0; +			uint8_t offset = 1; +			uint64_t tmp_val; +			tmp_val = op[0].value; +			offset += (prefix != 0); +			tmp_val -= offset+op_size[0]; +			tmp_val -= address; +			switch (rs) { +				default: max_sign = (int8_t )(1 <<  7); break; +				case 1 : max_sign = (int16_t)(1 << 15); break; +				case 2 : max_sign = (int32_t)(1 << 31); break; +				case 3 : max_sign = (int64_t)((uint64_t)1 << 63); break; +			} +			if ((int64_t)tmp_val > ~(int64_t)max_sign || (int64_t)tmp_val < (int64_t)max_sign) { +				offset += (!rs); +				rs += (rs <= 3); +				op_size[0] = (1 << rs); +				tmp_val = op[i].value; +				tmp_val -= offset+op_size[0]; +				tmp_val -= address; +				prefix = ((rs << 4) | 3); +			} +			op[0].value = tmp_val; +			is_ortho = 0; +		} else if (id != TOK_ORTHO) { +			if (!is_eind && is_valid && (is_mem || is_idx)) {  				if (of != 0xFF) {  					i = 8;  					for (; i <= 64; i += 8, j++) {  						max_val |= ((uint64_t)1 << (i-1)); -						if ((int64_t)val.u64 >= ~(int64_t)(max_val) || (int64_t)val.u64 <= (int64_t)(max_val)) { +						if ((int64_t)op[0].value >= ~(int64_t)(max_val) || (int64_t)op[0].value <= (int64_t)(max_val)) {  							opsize = j;  							break;  						} @@ -474,12 +740,20 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,  				} else {  					for (; i <= 64; i += 8, j++) {  						max_val |= (0xFF << i); -						if (val.u64 <= max_val) { +						if (op[0].value <= max_val) {  							opsize = j;  							break;  						}  					}  				} +				if (is_idx) { +					switch (op[1].id) { +						case REG_X: type = (op[0].id == MEM_IND || (of == 1 && op[0].id == MEM_ZMR && op[0].is_ind)) ? INDX : ZMX; break; +						case REG_Y: type = (op[0].id == MEM_IND || (of == 1 && op[0].id == MEM_ZMR && op[0].is_ind)) ? INDY : ZMY; break; +					} +				} else { +					type = (op[0].id == MEM_IND || (of == 1 && op[0].id == MEM_ZMR && op[0].is_ind)) ? IND : 0xFF; +				}  				type2 = type;  				if (type == 0xFF || (id == TOK_EXTOP && type2 != 0xFF)) {  					switch (opsize-1) { @@ -520,71 +794,192 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,  								opcode += 0x04;  							} else if (am & AM_ZM2) {  								opcode += 0x20; +							} else { +								is_ortho = 1;  							}  							break;  						case ZMX:  							if (am & AM_ZMX) {  								opcode += (id == TOK_OPCODE) ? 0x06 : 0x54; +							} else { +								is_ortho = 1;  							}  							break;  						case ZMY:  							if (am & AM_ZMY) {  								opcode += 0x14; +							} else { +								is_ortho = 1;  							}  							break;  						case INDX:  							if (am & AM_INDX) {  								opcode += (id == TOK_OPCODE) ? 0x16 : 0x94;  								break; +							} else { +								is_ortho = 1;  							}  							/* Falls Through. */  						case IND:  						case INDY:  							if ((id == TOK_OPCODE) && (am & (AM_IND|AM_INDY|AM_INDX2))) {  								opcode = ind_ops[get_ind(instr, type, dbg)]; -							} else { +							} else if (id = TOK_EXTOP) {  								opcode += (type == IND) ? 0x44 : 0x84; +							} else { +								is_ortho = 1;  							}  							break;  						case ABS:  							if (am & AM_ABS) {  								opcode += 0x10; +							} else { +								is_ortho = 1;  							}  							break;  						case ABSX:  							if (am & AM_ABX) {  								opcode += 0x50; +							} else { +								is_ortho = 1;  							}  							break;  						case ABSY:  							if (am & AM_ABY) {  								opcode += 0x00; +							} else { +								is_ortho = 1;  							}  							break;  						case AIND:  							if (am & AM_AIND) {  								opcode += 0x40; +							} else { +								is_ortho = 1;  							}  							break;  						case AINDX:  							if (am & AM_AINDX) {  								opcode += 0x90; +							} else { +								is_ortho = 1;  							}  							break;  						case AINDY:  							if (am & AM_AINDY) {  								opcode += 0x80; +							} else { +								is_ortho = 1;  							}  							break;  					} -					tmp = opsize; +					op_size[0] = opsize;  				} -				break; + +			} else if (op[1].type == 0xFF) { +				if (!op[0].type) { +					if (op[0].id == REG_B && (am & AM_BREG)) { +						opcode += 0x14; +					} else if (op[0].id == REG_A && (am & AM_IMPL)) { +						opcode = opcode; +					} else { +						is_ortho = 1; +					} +				} else { +					if (is_eind && (am & AM_EIND|AM_EIND2)) { +						int eind_type = ((am & AM_EIND2) != 0); +						switch (eind_type) { +							case 0: opcode = (id == TOK_EXTOP) ? opcode+0x14 : opcode+0x10; break; +							case 1: opcode = (id == TOK_EXTOP) ? opcode+0x01 : eind_base_ops[get_eind(instr, dbg)]; break; +						} +					} else if ((op[0].id == MEM_IMM) && (am & AM_IMM)) { +						rs = (rs != 0xFF) ? rs : 0; +						op_size[0] = (1 << rs); +					} else { +						is_ortho = 1; +					} +				} +			} else { +				is_ortho = 1; +			} +		} +		if (is_ortho) { +			ext_prefix = 0x1D; +			if (id == TOK_EXTOP) { +				opcode = ext_ortho_ops[get_ext_ortho(instr, dbg)]; +			} +			for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { +				int i2 = 0; +				int j = 0; +				(op[i].type == 1) ? (opcode |= (1 << (3+!i))) : (opcode &= ~(1 << (3+!i))); +				if (op[i].type == 1 && (am & AM_ORTHO|AM_ORTHO2)) { +					switch (op[i].id) { +						case MEM_RIND: break; +						case MEM_IMM: +							rs = (rs != 0xFF) ? rs : 0; +							op_size[i] = (1 << rs); +							break; +						case MEM_ZRIND: +						case MEM_ZINDR: +						case MEM_ZMR: +						case MEM_IND: +						default: +							if (of != 0xFF) { +								max_val = 0; +								for (i2 = 8, j = 1; i2 <= 64; i2 += 8, j++) { +									max_val |= ((uint64_t)1 << (i2-1)); +									if ((int64_t)op[i].value >= ~(int64_t)(max_val) || (int64_t)op[i].value <= (int64_t)(max_val)) { +										opsize = j; +										break; +									} +								} +							} else { +								max_val = 0; +								for (i2 = 0, j = 1; i2 <= 64; i2 += 8, j++) { +									max_val |= (0xFF << i2); +									if (op[i].value <= max_val) { +										opsize = j; +										break; +									} +								} +							} +							switch (opsize-1) { +								case 0: case 2: case 5: case 3: type = ZM ; break; +								case 1: case 4: case 6: case 7: type = ABS; break; +							} +							switch (op[i].id) { +								case MEM_IND  : op[i].id = (type == ABS) ? MEM_AIND  : op[i].id; break; +								case MEM_ZMR  : op[i].id = (type == ABS) ? MEM_ABSR  : op[i].id; break; +								case MEM_ZRIND: op[i].id = (type == ABS) ? MEM_ARIND : op[i].id; break; +								case MEM_ZINDR: op[i].id = (type == ABS) ? MEM_AINDR : op[i].id; break; +								case 0xFF     : op[i].id = (type == ABS) ? MEM_ABS   :   MEM_ZM; break; +							} +							if (opsize) { +								uint8_t is_abs = (type == ABS); +								if (!is_abs) { +									switch (opsize) { +										case 2: opsize = 3; break; +										case 5: opsize = 6; break; +									} +								} +								prefix |= amp[opsize-1]; +							} +							op_size[i] = opsize; +							if (isasm /*&& dbg*/) { +								printf("op_size[%i]: %i, opsize: %u\n", i, op_size[i], opsize); +							} +							break; +					} +				} +			}  		} -		inst_size = write_inst(prefix, ext_prefix, opcode, val.u64, address, tmp, isasm, dbg); +		inst_size = write_inst(prefix, ext_prefix, opcode, op, address, op_size, isasm, /*dbg*/isasm);  		address += inst_size;  		bc->progsize += inst_size; +		if (isasm /*&& dbg*/) { +			printf("inst_size: $%X, bc->progsize: $%"PRIX64"\n", inst_size, bc->progsize); +		}  	}  	return address;  } @@ -596,14 +991,15 @@ uint64_t parse_tokens(token *t, line **l, bytecount *bc, uint8_t isasm, uint64_t  				switch (t->type) {  					case DIR_STRUCT:  					case DIR_UNION : handle_struct(l, address, 0, dbg); break; -					case DIR_RES: t = t->next; address += get_val(t, address, 3, dbg); break; -					case DIR_ORG: t = t->next; address  = get_val(t, address, 3, dbg); break; +					case DIR_RES: t = t->next; address += get_val(t, address, 3, 0xFF, 0, dbg); break; +					case DIR_ORG: t = t->next; address  = get_val(t, address, 3, 0xFF, 0, dbg); break;  					case DIR_BYTE:  					case DIR_WORD:  					case DIR_DWORD:  					case DIR_QWORD: address = handle_directive(t, bc, isasm, address, dbg); break;  				}  				break; +			case TOK_ORTHO :  			case TOK_EXTOP :  			case TOK_OPCODE: address = handle_opcode(t, bc, isasm, address, dbg); break;  			case TOK_COMMENT: break; @@ -618,6 +1014,7 @@ token *make_token(uint8_t id, uint8_t type, uint8_t space, uint8_t tab, uint64_t  	new_tok->id = id;  	new_tok->type = type; +	new_tok->subtype = 0xFF;  	new_tok->tab = tab;  	new_tok->space = space; @@ -806,29 +1203,13 @@ void fix_symtree(line *l) {  						if ((!is_structsym) || (isanon && is_structsym)) {  							isanon++;  						} -					} else if (t->type == DIR_ENDSTRUCT || t->type == DIR_ENDUNION) { -						is_struct--; -						int skip = 0; -						if (isanon > 0) { -							if ((cur_sym->up && !cur_sym->up->isanon) || (sym_struct && sym_struct->isanon)) { -								isanon--; -							} -							skip = (!isanon); -						} -						if ((int)(is_struct-isanon) > 0 && !skip && cur_sym->up) { -							for (sym_struct = s->up; sym_struct->prev && !sym_struct->isanon; sym_struct = sym_struct->prev); -							s = s->up; -							cur_sym = (cur_sym->up != NULL) ? cur_sym->up : s; -						}  					}  					break;  			} -			lt = t;  		}  	}  } -  static inline void free_tokens(token *t) {  	token *tok;  	if (t != NULL) {  | 
