1 /*
2 ===========================================================================
3 vm_x86_64_assembler.c -- assembler for x86-64
4 
5 Copyright (C) 2007 Ludwig Nussel <ludwig.nussel@suse.de>, Novell inc.
6 
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11 
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdarg.h>
27 
28 typedef unsigned char u8;
29 typedef unsigned short u16;
30 typedef unsigned int u32;
31 typedef unsigned long u64;
32 
33 static char* out;
34 static unsigned compiledOfs;
35 static unsigned assembler_pass;
36 
37 static const char* cur_line;
38 
39 static FILE* fout;
40 
41 #define MIN(a,b)  ((a) < (b) ? (a) : (b))
42 #define MAX(a,b)  ((a) > (b) ? (a) : (b))
43 
44 #define crap(fmt, args...) do { \
45 	_crap(__FUNCTION__, fmt, ##args); \
46 } while(0)
47 
48 #define CRAP_INVALID_ARGS crap("invalid arguments %s, %s", argtype2str(arg1.type),argtype2str(arg2.type));
49 
50 #ifdef DEBUG
51 #define debug(fmt, args...) printf(fmt, ##args)
52 #else
53 #define debug(fmt, args...)
54 #endif
55 
_crap(const char * func,const char * fmt,...)56 static void _crap(const char* func, const char* fmt, ...)
57 {
58 	va_list ap;
59 	fprintf(stderr, "%s() - ", func);
60 	va_start(ap, fmt);
61 	vfprintf(stderr, fmt, ap);
62 	va_end(ap);
63 	fputc('\n', stderr);
64 	if(cur_line && cur_line[0])
65 		fprintf(stderr, "-> %s\n", cur_line);
66 	exit(1);
67 }
68 
emit1(unsigned char v)69 static void emit1(unsigned char v)
70 {
71 	if(assembler_pass)
72 	{
73 		out[compiledOfs++] = v;
74 		if(fout) fwrite(&v, 1, 1, fout);
75 		debug("%02hhx ", v);
76 	}
77 	else
78 	{
79 		++compiledOfs;
80 	}
81 }
82 
emit2(u16 v)83 static inline void emit2(u16 v)
84 {
85 	emit1(v&0xFF);
86 	emit1((v>>8)&0xFF);
87 }
88 
emit4(u32 v)89 static inline void emit4(u32 v)
90 {
91 	emit1(v&0xFF);
92 	emit1((v>>8)&0xFF);
93 	emit1((v>>16)&0xFF);
94 	emit1((v>>24)&0xFF);
95 }
96 
emit8(u64 v)97 static inline void emit8(u64 v)
98 {
99 	emit4(v&0xFFFFFFFF);
100 	emit4((v>>32)&0xFFFFFFFF);
101 }
102 
103 enum {
104 	REX_W = 0x08,
105 	REX_R = 0x04,
106 	REX_X = 0x02,
107 	REX_B = 0x01,
108 };
109 
110 enum {
111 	MODRM_MOD_00 = 0x00,
112 	MODRM_MOD_01 = 0x01 << 6,
113 	MODRM_MOD_10 = 0x02 << 6,
114 	MODRM_MOD_11 = 0x03 << 6,
115 	MODRM_RM_SIB = 0x04,
116 };
117 
118 typedef enum
119 {
120 	T_NONE      = 0x00,
121 	T_REGISTER  = 0x01,
122 	T_IMMEDIATE = 0x02,
123 	T_MEMORY    = 0x04,
124 	T_LABEL     = 0x08,
125 	T_ABSOLUTE  = 0x80
126 } argtype_t;
127 
128 typedef enum {
129 	R_8   = 0x100,
130 	R_16  = 0x200,
131 	R_64  = 0x800,
132 	R_MSZ = 0xF00,  // size mask
133 	R_XMM = 0x2000, // xmm register. year, sucks
134 	R_EAX =  0x00,
135 	R_EBX =  0x03,
136 	R_ECX =  0x01,
137 	R_EDX =  0x02,
138 	R_ESI =  0x06,
139 	R_EDI =  0x07,
140 	R_ESP =  0x04,
141 	R_RAX =  R_EAX | R_64,
142 	R_RBX =  R_EBX | R_64,
143 	R_RCX =  R_ECX | R_64,
144 	R_RDX =  R_EDX | R_64,
145 	R_RSI =  R_ESI | R_64,
146 	R_RDI =  R_EDI | R_64,
147 	R_RSP =  R_ESP | R_64,
148 	R_R8  =  0x08  | R_64,
149 	R_R9  =  0x09  | R_64,
150 	R_R10 =  0x0A  | R_64,
151 	R_R15 =  0x0F  | R_64,
152 	R_AL  =  R_EAX | R_8,
153 	R_AX  =  R_EAX | R_16,
154 	R_CL  =  R_ECX | R_8,
155 	R_XMM0 = 0x00  | R_XMM,
156 	R_MGP =  0x0F, // mask for general purpose registers
157 } reg_t;
158 
159 typedef enum {
160 	MODRM_SIB = 0,
161 	MODRM_NOSIB = 0x3,
162 } modrm_sib_t;
163 
164 typedef struct {
165 	unsigned disp;
166 	argtype_t basetype;
167 	union {
168 		u64 imm;
169 		reg_t reg;
170 	} base;
171 	argtype_t indextype;
172 	union {
173 		u64 imm;
174 		reg_t reg;
175 	} index;
176 	unsigned scale;
177 } memref_t;
178 
179 #define LABELLEN 32
180 
181 typedef struct {
182 	argtype_t type;
183 	union {
184 		u64 imm;
185 		reg_t reg;
186 		memref_t mem;
187 		char label[LABELLEN];
188 	} v;
189 	int absolute:1;
190 } arg_t;
191 
192 typedef void (*emitfunc)(const char* op, arg_t arg1, arg_t arg2, void* data);
193 
194 typedef struct {
195 	char* mnemonic;
196 	emitfunc func;
197 	void* data;
198 } op_t;
199 
200 typedef struct {
201 	u8 xmmprefix;
202 	u8 subcode; // in modrm
203 	u8 rmcode;  // opcode for reg/mem, reg
204 	u8 mrcode;  // opcode for reg, reg/mem
205 	u8 rcode8;  // opcode for reg8/mem8
206 	u8 rcode;  // opcode for reg/mem
207 } opparam_t;
208 
209 /* ************************* */
210 
hashkey(const char * string,unsigned len)211 static unsigned hashkey(const char *string, unsigned len) {
212 	unsigned register hash, i;
213 
214 	hash = 0;
215 	for (i = 0; i < len && string[i] != '\0'; ++i) {
216 		hash += string[i] * (119 + i);
217 	}
218 	hash = (hash ^ (hash >> 10) ^ (hash >> 20));
219 	return hash;
220 }
221 
222 struct hashentry {
223 	char* label;
224 	unsigned address;
225 	struct hashentry* next;
226 };
227 static struct hashentry* labelhash[1021];
228 
229 // no dup check!
hash_add_label(const char * label,unsigned address)230 static void hash_add_label(const char* label, unsigned address)
231 {
232 	struct hashentry* h;
233 	unsigned i = hashkey(label, -1U);
234 	i %= sizeof(labelhash)/sizeof(labelhash[0]);
235 	h = malloc(sizeof(struct hashentry));
236 	h->label = strdup(label);
237 	h->address = address;
238 	h->next = labelhash[i];
239 	labelhash[i] = h;
240 }
241 
lookup_label(const char * label)242 static unsigned lookup_label(const char* label)
243 {
244 	struct hashentry* h;
245 	unsigned i = hashkey(label, -1U);
246 	i %= sizeof(labelhash)/sizeof(labelhash[0]);
247 	for(h = labelhash[i]; h; h = h->next )
248 	{
249 		if(!strcmp(h->label, label))
250 			return h->address;
251 	}
252 	if(assembler_pass)
253 		crap("label %s undefined", label);
254 	return 0;
255 }
256 
labelhash_free(void)257 static void labelhash_free(void)
258 {
259 	struct hashentry* h;
260 	unsigned i;
261 	unsigned z = 0, min = -1U, max = 0, t = 0;
262 	for ( i = 0; i < sizeof(labelhash)/sizeof(labelhash[0]); ++i)
263 	{
264 		unsigned n = 0;
265 		h = labelhash[i];
266 		while(h)
267 		{
268 			struct hashentry* next = h->next;
269 			free(h->label);
270 			free(h);
271 			h = next;
272 			++n;
273 		}
274 		t+=n;
275 		if(!n) ++z;
276 		//else printf("%u\n", n);
277 		min = MIN(min, n);
278 		max = MAX(max, n);
279 	}
280 	printf("total %u, hsize %lu, zero %u, min %u, max %u\n", t, sizeof(labelhash)/sizeof(labelhash[0]), z, min, max);
281 	memset(labelhash, 0, sizeof(labelhash));
282 }
283 
284 /* ************************* */
285 
286 
argtype2str(argtype_t t)287 static const char* argtype2str(argtype_t t)
288 {
289 	switch(t)
290 	{
291 		case T_NONE: return "none";
292 		case T_REGISTER: return "register";
293 		case T_IMMEDIATE: return "immediate";
294 		case T_MEMORY: return "memory";
295 		case T_LABEL: return "label";
296 		default: crap("invalid type");
297 	}
298 	/* not reached */
299 	return T_NONE;
300 }
301 
302 /* ************************* */
303 
iss8(u64 v)304 static inline int iss8(u64 v)
305 {
306 	return (labs(v) <= 0x80);
307 }
308 
isu8(u64 v)309 static inline int isu8(u64 v)
310 {
311 	return (v <= 0xff);
312 }
313 
iss16(u64 v)314 static inline int iss16(u64 v)
315 {
316 	return (labs(v) <= 0x8000);
317 }
318 
isu16(u64 v)319 static inline int isu16(u64 v)
320 {
321 	return (v <= 0xffff);
322 }
323 
iss32(u64 v)324 static inline int iss32(u64 v)
325 {
326 	return (labs(v) <= 0x80000000);
327 }
328 
isu32(u64 v)329 static inline int isu32(u64 v)
330 {
331 	return (v <= 0xffffffff);
332 }
333 
emit_opsingle(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)334 static void emit_opsingle(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
335 {
336 	u8 op = (u8)((unsigned long) data);
337 
338 	if(arg1.type != T_NONE || arg2.type != T_NONE)
339 		CRAP_INVALID_ARGS;
340 
341 	emit1(op);
342 }
343 
emit_opsingle16(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)344 static void emit_opsingle16(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
345 {
346 	emit1(0x66);
347 	emit_opsingle(mnemonic, arg1, arg2, data);
348 }
349 
compute_rexmodrmsib(u8 * rex_r,u8 * modrm_r,u8 * sib_r,arg_t * arg1,arg_t * arg2)350 static void compute_rexmodrmsib(u8* rex_r, u8* modrm_r, u8* sib_r, arg_t* arg1, arg_t* arg2)
351 {
352 	u8 rex = 0;
353 	u8 modrm = 0;
354 	u8 sib = 0;
355 
356 	if((arg1->type == T_REGISTER && arg2->type == T_REGISTER)
357 	&& ((arg1->v.reg & R_MSZ) != (arg2->v.reg & R_MSZ))
358 	&& !((arg1->v.reg & R_XMM) || (arg2->v.reg & R_XMM)))
359 		crap("both registers must be of same width");
360 
361 	if((arg1->type == T_REGISTER && arg1->v.reg & R_64)
362 	|| (arg2->type == T_REGISTER && arg2->v.reg & R_64))
363 	{
364 		rex |= REX_W;
365 	}
366 
367 	if(arg1->type == T_REGISTER)
368 	{
369 		if((arg1->v.reg & R_MGP) > 0x07)
370 			rex |= REX_R;
371 
372 		modrm |= (arg1->v.reg & 0x07) << 3;
373 	}
374 
375 	if(arg2->type == T_REGISTER)
376 	{
377 		if((arg2->v.reg & R_MGP) > 0x07)
378 			rex |= REX_B;
379 
380 		modrm |= (arg2->v.reg & 0x07);
381 	}
382 
383 	if(arg2->type == T_MEMORY)
384 	{
385 		if((arg2->v.mem.basetype == T_REGISTER && !(arg2->v.mem.base.reg & R_64))
386 		|| (arg2->v.mem.indextype == T_REGISTER && !(arg2->v.mem.index.reg & R_64)))
387 		{
388 			crap("only 64bit base/index registers are %x %x", arg2->v.mem.base.reg, arg2->v.mem.index.reg);
389 		}
390 
391 		if(arg2->v.mem.indextype == T_REGISTER)
392 		{
393 			modrm |= MODRM_RM_SIB;
394 			if(!arg2->v.mem.disp)
395 			{
396 				modrm |= MODRM_MOD_00;
397 			}
398 			else if(iss8(arg2->v.mem.disp))
399 			{
400 				modrm |= MODRM_MOD_01;
401 			}
402 			else if(isu32(arg2->v.mem.disp))
403 			{
404 				modrm |= MODRM_MOD_10;
405 			}
406 			else
407 			{
408 				crap("invalid displacement");
409 			}
410 
411 			if((arg2->v.mem.index.reg & R_MGP) > 0x07)
412 				rex |= REX_X;
413 
414 			if((arg2->v.mem.base.reg & R_MGP) > 0x07)
415 				rex |= REX_B;
416 
417 			if(arg2->v.mem.basetype != T_REGISTER)
418 				crap("base must be register");
419 			switch(arg2->v.mem.scale)
420 			{
421 				case 1: break;
422 				case 2: sib |= 1 << 6; break;
423 				case 4: sib |= 2 << 6; break;
424 				case 8: sib |= 3 << 6; break;
425 			}
426 			sib |= (arg2->v.mem.index.reg & 0x07) << 3;
427 			sib |= (arg2->v.mem.base.reg & 0x07);
428 		}
429 		else if(arg2->v.mem.indextype == T_NONE)
430 		{
431 			if(!arg2->v.mem.disp)
432 			{
433 				modrm |= MODRM_MOD_00;
434 			}
435 			else if(iss8(arg2->v.mem.disp))
436 			{
437 				modrm |= MODRM_MOD_01;
438 			}
439 			else if(isu32(arg2->v.mem.disp))
440 			{
441 				modrm |= MODRM_MOD_10;
442 			}
443 			else
444 			{
445 				crap("invalid displacement");
446 			}
447 
448 			if(arg2->v.mem.basetype != T_REGISTER)
449 				crap("todo: base != register");
450 
451 			if((arg2->v.mem.base.reg & R_MGP) > 0x07)
452 				rex |= REX_B;
453 
454 			modrm |= arg2->v.mem.base.reg & 0x07;
455 		}
456 		else
457 		{
458 			crap("invalid indextype");
459 		}
460 	}
461 	else
462 	{
463 		modrm |= MODRM_MOD_11;
464 	}
465 
466 	if(rex)
467 		rex |= 0x40; // XXX
468 
469 	*rex_r = rex;
470 	*modrm_r = modrm;
471 	*sib_r = sib;
472 }
473 
maybe_emit_displacement(arg_t * arg)474 static void maybe_emit_displacement(arg_t* arg)
475 {
476 	if(arg->type != T_MEMORY)
477 		return;
478 
479 	if(arg->v.mem.disp)
480 	{
481 		if(iss8(arg->v.mem.disp))
482 		{
483 			emit1((u8)arg->v.mem.disp);
484 		}
485 		else if(isu32(arg->v.mem.disp))
486 		{
487 			emit4(arg->v.mem.disp);
488 		}
489 		else
490 		{
491 			crap("invalid displacement");
492 		}
493 	}
494 }
495 
496 /* one byte operator with register added to operator */
emit_opreg(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)497 static void emit_opreg(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
498 {
499 	u8 op = (u8)((unsigned long) data);
500 
501 	if(arg1.type != T_REGISTER || arg2.type != T_NONE)
502 		CRAP_INVALID_ARGS;
503 
504 	if((arg1.v.reg & R_MGP) > 0x07)
505 		emit1(0x40 | REX_B);
506 
507 	op |= (arg1.v.reg & 0x07);
508 
509 	emit1(op);
510 }
511 
512 /* operator which operates on reg/mem */
emit_op_rm(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)513 static void emit_op_rm(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
514 {
515 	u8 rex, modrm, sib;
516 	opparam_t* params = data;
517 
518 	if((arg1.type != T_REGISTER && arg1.type != T_MEMORY) || arg2.type != T_NONE)
519 		CRAP_INVALID_ARGS;
520 
521 	compute_rexmodrmsib(&rex, &modrm, &sib, &arg2, &arg1);
522 
523 	modrm |= params->subcode << 3;
524 
525 	if(arg1.v.reg & R_16)
526 		emit1(0x66);
527 
528 	if(rex) emit1(rex);
529 	if(arg1.v.reg & R_8)
530 		emit1(params->rcode8); // op reg8/mem8,
531 	else
532 		emit1(params->rcode); // op reg/mem,
533 	emit1(modrm);
534 	if((modrm & 0x07) == MODRM_RM_SIB)
535 		emit1(sib);
536 
537 	maybe_emit_displacement(&arg1);
538 }
539 
540 /* operator which operates on reg/mem with cl */
emit_op_rm_cl(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)541 static void emit_op_rm_cl(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
542 {
543 	u8 rex, modrm, sib;
544 	opparam_t* params = data;
545 
546 	if(arg2.type != T_REGISTER || arg1.type != T_REGISTER)
547 		CRAP_INVALID_ARGS;
548 
549 	if((arg1.v.reg & R_MGP) != R_ECX && !(arg1.v.reg & R_8))
550 		crap("only cl register is valid");
551 
552 	arg1.type = T_NONE; // don't complain, we know it's cl anyways
553 
554 	compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
555 
556 	modrm |= params->subcode << 3;
557 
558 	if(arg2.v.reg & R_16)
559 		emit1(0x66);
560 
561 	if(rex) emit1(rex);
562 	if(arg2.v.reg & R_8)
563 		emit1(params->rcode8); // op reg8/mem8,
564 	else
565 		emit1(params->rcode); // op reg/mem,
566 	emit1(modrm);
567 	if((modrm & 0x07) == MODRM_RM_SIB)
568 		emit1(sib);
569 
570 	maybe_emit_displacement(&arg2);
571 }
572 
emit_mov(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)573 static void emit_mov(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
574 {
575 	u8 rex = 0;
576 	u8 modrm = 0;
577 	u8 sib = 0;
578 
579 	if(arg1.type == T_IMMEDIATE && arg2.type == T_REGISTER)
580 	{
581 		u8 op = 0xb8;
582 
583 		if(arg2.v.reg & R_8)
584 		{
585 			if(!isu8(arg1.v.imm))
586 				crap("value too large for 8bit register");
587 
588 			op = 0xb0;
589 		}
590 		else if(arg2.v.reg & R_16)
591 		{
592 			if(!isu16(arg1.v.imm))
593 				crap("value too large for 16bit register");
594 			emit1(0x66);
595 		}
596 		else if(!arg2.v.reg & R_64)
597 		{
598 			if(!isu32(arg1.v.imm))
599 				crap("value too large for 32bit register");
600 		}
601 
602 		compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
603 
604 		if(rex) emit1(rex);
605 
606 		op |= (arg2.v.reg & 0x07);
607 
608 		emit1(op);
609 
610 		if(arg2.v.reg & R_8) emit1(arg1.v.imm);
611 		else if(arg2.v.reg & R_16) emit2(arg1.v.imm);
612 		else if(arg2.v.reg & R_64) emit8(arg1.v.imm);
613 		else emit4(arg1.v.imm);
614 	}
615 	else if(arg1.type == T_IMMEDIATE && arg2.type == T_MEMORY)
616 	{
617 		if(!iss32(arg1.v.imm))
618 		{
619 			crap("only 32bit immediates supported");
620 		}
621 
622 		compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
623 		if(rex) emit1(rex);
624 		emit1(0xc7); // mov reg/mem, imm
625 		emit1(modrm);
626 		if((modrm & 0x07) == MODRM_RM_SIB)
627 			emit1(sib);
628 
629 		emit4(arg1.v.imm);
630 	}
631 	else if(arg1.type == T_REGISTER && arg2.type == T_REGISTER) // XXX: same as next
632 	{
633 		if(arg1.type != T_REGISTER || arg2.type != T_REGISTER)
634 			crap("both args must be registers");
635 
636 		if((arg1.v.reg & R_MSZ) != (arg2.v.reg & R_MSZ))
637 			crap("both registers must be same width");
638 
639 		compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
640 
641 		if(rex) emit1(rex);
642 		emit1(0x89); // mov reg reg/mem,
643 		emit1(modrm);
644 	}
645 	else if(arg1.type == T_REGISTER && arg2.type == T_MEMORY)
646 	{
647 		compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
648 
649 		if(arg1.v.reg & R_16)
650 			emit1(0x66);
651 
652 		if(rex) emit1(rex);
653 		if(arg1.v.reg & R_8)
654 			emit1(0x88); // mov reg reg/mem,
655 		else
656 			emit1(0x89); // mov reg reg/mem,
657 		emit1(modrm);
658 		if((modrm & 0x07) == MODRM_RM_SIB)
659 			emit1(sib);
660 
661 		maybe_emit_displacement(&arg2);
662 	}
663 	else if(arg1.type == T_MEMORY && arg2.type == T_REGISTER)
664 	{
665 		compute_rexmodrmsib(&rex, &modrm, &sib, &arg2, &arg1);
666 
667 		if(arg2.v.reg & R_16)
668 			emit1(0x66);
669 
670 		if(rex) emit1(rex);
671 		if(arg2.v.reg & R_8)
672 			emit1(0x8a); // mov reg/mem, reg
673 		else
674 			emit1(0x8b); // mov reg/mem, reg
675 		emit1(modrm);
676 		if((modrm & 0x07) == MODRM_RM_SIB)
677 			emit1(sib);
678 
679 		maybe_emit_displacement(&arg1);
680 	}
681 	else
682 		CRAP_INVALID_ARGS;
683 }
684 
emit_subaddand(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)685 static void emit_subaddand(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
686 {
687 	u8 rex = 0;
688 	u8 modrm = 0;
689 	u8 sib = 0;
690 
691 	opparam_t* params = data;
692 
693 	if(arg1.type == T_IMMEDIATE && arg2.type == T_REGISTER)
694 	{
695 		if(!iss32(arg1.v.imm))
696 		{
697 			crap("only 8 and 32 bit immediates supported");
698 		}
699 
700 		compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
701 
702 		modrm |= params->subcode << 3;
703 
704 		if(rex) emit1(rex);
705 #if 0
706 		if(isu8(arg1.v.imm))
707 		{
708 			emit1(0x83); // sub reg/mem, imm8
709 			emit1(modrm);
710 			emit1(arg1.v.imm&0xFF);
711 		}
712 		else
713 #endif
714 		{
715 			emit1(0x81); // sub reg/mem, imm32
716 			emit1(modrm);
717 			emit4(arg1.v.imm);
718 		}
719 	}
720 	else if(arg1.type == T_REGISTER && (arg2.type == T_MEMORY || arg2.type == T_REGISTER))
721 	{
722 		compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
723 
724 		if(rex) emit1(rex);
725 		emit1(params->rmcode); // sub reg/mem, reg
726 		emit1(modrm);
727 		if(arg2.type == T_MEMORY && (modrm & 0x07) == MODRM_RM_SIB)
728 			emit1(sib);
729 
730 		maybe_emit_displacement(&arg2);
731 	}
732 	else if(arg1.type == T_MEMORY && arg2.type == T_REGISTER && params->mrcode)
733 	{
734 		compute_rexmodrmsib(&rex, &modrm, &sib, &arg2, &arg1);
735 
736 		if(rex) emit1(rex);
737 		emit1(params->mrcode); // sub reg, reg/mem
738 		emit1(modrm);
739 		if((modrm & 0x07) == MODRM_RM_SIB)
740 			emit1(sib);
741 
742 		maybe_emit_displacement(&arg1);
743 	}
744 	else
745 		CRAP_INVALID_ARGS;
746 }
747 
emit_condjump(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)748 static void emit_condjump(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
749 {
750 	unsigned off;
751 	int disp;
752 	unsigned char opcode = (unsigned char)(((unsigned long)data)&0xFF);
753 
754 	if(arg1.type != T_LABEL || arg2.type != T_NONE)
755 		crap("%s: argument must be label", mnemonic);
756 
757 	emit1(opcode);
758 
759 	off = lookup_label(arg1.v.label);
760 	disp = off-(compiledOfs+1);
761 	if(assembler_pass && abs(disp) > 127)
762 		crap("cannot jump that far (%x -> %x = %x)", compiledOfs, off, disp);
763 
764 	emit1(disp);
765 }
766 
emit_jmp(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)767 static void emit_jmp(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
768 {
769 	if((arg1.type != T_LABEL && arg1.type != T_REGISTER && arg1.type != T_MEMORY) || arg2.type != T_NONE)
770 		CRAP_INVALID_ARGS;
771 
772 	if(arg1.type == T_LABEL)
773 	{
774 		unsigned off;
775 		int disp;
776 
777 		off = lookup_label(arg1.v.label);
778 		disp = off-(compiledOfs+5);
779 		emit1(0xe9);
780 		emit4(disp);
781 	}
782 	else
783 	{
784 		u8 rex, modrm, sib;
785 
786 		if(arg1.type == T_REGISTER)
787 		{
788 			if(!arg1.absolute)
789 				crap("jmp must be absolute");
790 
791 			if((arg1.v.reg & R_64) != R_64)
792 				crap("register must be 64bit");
793 
794 			arg1.v.reg ^= R_64; // no rex required for call
795 		}
796 
797 		compute_rexmodrmsib(&rex, &modrm, &sib, &arg2, &arg1);
798 
799 		modrm |= 0x4 << 3;
800 
801 		if(rex) emit1(rex);
802 		emit1(0xff);
803 		emit1(modrm);
804 		if((modrm & 0x07) == MODRM_RM_SIB)
805 			emit1(sib);
806 		maybe_emit_displacement(&arg1);
807 	}
808 }
809 
emit_call(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)810 static void emit_call(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
811 {
812 	u8 rex, modrm, sib;
813 
814 	if(arg1.type != T_REGISTER || arg2.type != T_NONE)
815 		CRAP_INVALID_ARGS;
816 
817 	if(!arg1.absolute)
818 		crap("call must be absolute");
819 
820 	if((arg1.v.reg & R_64) != R_64)
821 		crap("register must be 64bit");
822 
823 	arg1.v.reg ^= R_64; // no rex required for call
824 
825 	compute_rexmodrmsib(&rex, &modrm, &sib, &arg2, &arg1);
826 
827 	modrm |= 0x2 << 3;
828 
829 	if(rex) emit1(rex);
830 	emit1(0xff);
831 	emit1(modrm);
832 }
833 
834 
emit_twobyte(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)835 static void emit_twobyte(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
836 {
837 	u8 rex, modrm, sib;
838 
839 	opparam_t* params = data;
840 
841 	if(arg1.type == T_REGISTER && (arg2.type == T_MEMORY || arg2.type == T_REGISTER))
842 	{
843 		compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
844 
845 		if(params->xmmprefix) emit1(params->xmmprefix);
846 		if(rex) emit1(rex);
847 		emit1(0x0f);
848 		emit1(params->rmcode); // sub reg/mem, reg
849 		emit1(modrm);
850 		if((modrm & 0x07) == MODRM_RM_SIB)
851 			emit1(sib);
852 
853 		maybe_emit_displacement(&arg2);
854 	}
855 	else if(arg1.type == T_MEMORY && arg2.type == T_REGISTER && params->mrcode)
856 	{
857 		compute_rexmodrmsib(&rex, &modrm, &sib, &arg2, &arg1);
858 
859 		if(params->xmmprefix) emit1(params->xmmprefix);
860 		if(rex) emit1(rex);
861 		emit1(0x0f);
862 		emit1(params->mrcode); // sub reg, reg/mem
863 		emit1(modrm);
864 		if((modrm & 0x07) == MODRM_RM_SIB)
865 			emit1(sib);
866 
867 		maybe_emit_displacement(&arg1);
868 	}
869 	else
870 		CRAP_INVALID_ARGS;
871 }
872 
873 static opparam_t params_add = { subcode: 0, rmcode: 0x01, };
874 static opparam_t params_or = { subcode: 1, rmcode: 0x09, };
875 static opparam_t params_and = { subcode: 4, rmcode: 0x21, };
876 static opparam_t params_sub = { subcode: 5, rmcode: 0x29, };
877 static opparam_t params_xor = { subcode: 6, rmcode: 0x31, };
878 static opparam_t params_cmp = { subcode: 6, rmcode: 0x39, mrcode: 0x3b, };
879 static opparam_t params_dec = { subcode: 1, rcode: 0xff, rcode8: 0xfe, };
880 static opparam_t params_sar = { subcode: 7, rcode: 0xd3, rcode8: 0xd2, };
881 static opparam_t params_shl = { subcode: 4, rcode: 0xd3, rcode8: 0xd2, };
882 static opparam_t params_shr = { subcode: 5, rcode: 0xd3, rcode8: 0xd2, };
883 static opparam_t params_idiv = { subcode: 7, rcode: 0xf7, rcode8: 0xf6, };
884 static opparam_t params_div = { subcode: 6, rcode: 0xf7, rcode8: 0xf6, };
885 static opparam_t params_imul = { subcode: 5, rcode: 0xf7, rcode8: 0xf6, };
886 static opparam_t params_mul = { subcode: 4, rcode: 0xf7, rcode8: 0xf6, };
887 static opparam_t params_neg = { subcode: 3, rcode: 0xf7, rcode8: 0xf6, };
888 static opparam_t params_not = { subcode: 2, rcode: 0xf7, rcode8: 0xf6, };
889 
890 static opparam_t params_cvtsi2ss = { xmmprefix: 0xf3, rmcode: 0x2a };
891 static opparam_t params_cvttss2si = { xmmprefix: 0xf3, rmcode: 0x2c };
892 static opparam_t params_addss = { xmmprefix: 0xf3, mrcode: 0x58 };
893 static opparam_t params_divss = { xmmprefix: 0xf3, mrcode: 0x5e };
894 static opparam_t params_movss = { xmmprefix: 0xf3, mrcode: 0x10, rmcode: 0x11 };
895 static opparam_t params_mulss = { xmmprefix: 0xf3, mrcode: 0x59 };
896 static opparam_t params_subss = { xmmprefix: 0xf3, mrcode: 0x5c };
897 static opparam_t params_ucomiss = { mrcode: 0x2e };
898 
899 static int ops_sorted = 0;
900 static op_t ops[] = {
901 	{ "addl", emit_subaddand, &params_add },
902 	{ "addq", emit_subaddand, &params_add },
903 	{ "addss", emit_twobyte, &params_addss },
904 	{ "andl", emit_subaddand, &params_and },
905 	{ "andq", emit_subaddand, &params_and },
906 	{ "callq", emit_call, NULL },
907 	{ "cbw", emit_opsingle16, (void*)0x98 },
908 	{ "cdq", emit_opsingle, (void*)0x99 },
909 	{ "cmpl", emit_subaddand, &params_cmp },
910 	{ "cmpq", emit_subaddand, &params_cmp },
911 	{ "cvtsi2ss", emit_twobyte, &params_cvtsi2ss },
912 	{ "cvttss2si", emit_twobyte, &params_cvttss2si },
913 	{ "cwde", emit_opsingle, (void*)0x98 },
914 	{ "decl", emit_op_rm, &params_dec },
915 	{ "decq", emit_op_rm, &params_dec },
916 	{ "divl", emit_op_rm, &params_div },
917 	{ "divq", emit_op_rm, &params_div },
918 	{ "divss", emit_twobyte, &params_divss },
919 	{ "idivl", emit_op_rm, &params_idiv },
920 	{ "imull", emit_op_rm, &params_imul },
921 	{ "int3", emit_opsingle, (void*)0xcc },
922 	{ "ja", emit_condjump, (void*)0x77 },
923 	{ "jbe", emit_condjump, (void*)0x76 },
924 	{ "jb", emit_condjump, (void*)0x72 },
925 	{ "je", emit_condjump, (void*)0x74 },
926 	{ "jl", emit_condjump, (void*)0x7c },
927 	{ "jmp", emit_jmp, NULL },
928 	{ "jmpq", emit_jmp, NULL },
929 	{ "jnae", emit_condjump, (void*)0x72 },
930 	{ "jna", emit_condjump, (void*)0x76 },
931 	{ "jnbe", emit_condjump, (void*)0x77 },
932 	{ "jnb", emit_condjump, (void*)0x73 },
933 	{ "jnc", emit_condjump, (void*)0x73 },
934 	{ "jne", emit_condjump, (void*)0x75 },
935 	{ "jnge", emit_condjump, (void*)0x7c },
936 	{ "jng", emit_condjump, (void*)0x7e },
937 	{ "jnle", emit_condjump, (void*)0x7f },
938 	{ "jnl", emit_condjump, (void*)0x7d },
939 	{ "jnz", emit_condjump, (void*)0x75 },
940 	{ "jp", emit_condjump, (void*)0x7a },
941 	{ "jz", emit_condjump, (void*)0x74 },
942 	{ "movb", emit_mov, NULL },
943 	{ "movl", emit_mov, NULL },
944 	{ "movq", emit_mov, NULL },
945 	{ "movss", emit_twobyte, &params_movss },
946 	{ "movw", emit_mov, NULL },
947 	{ "mull", emit_op_rm, &params_mul },
948 	{ "mulss", emit_twobyte, &params_mulss },
949 	{ "negl", emit_op_rm, &params_neg },
950 	{ "negq", emit_op_rm, &params_neg },
951 	{ "nop", emit_opsingle, (void*)0x90 },
952 	{ "notl", emit_op_rm, &params_not },
953 	{ "notq", emit_op_rm, &params_not },
954 	{ "or",   emit_subaddand, &params_or },
955 	{ "orl",  emit_subaddand, &params_or },
956 	{ "pop", emit_opreg, (void*)0x58 },
957 	{ "push", emit_opreg, (void*)0x50 },
958 	{ "ret", emit_opsingle, (void*)0xc3 },
959 	{ "sarl", emit_op_rm_cl, &params_sar },
960 	{ "shl", emit_op_rm_cl, &params_shl },
961 	{ "shrl", emit_op_rm_cl, &params_shr },
962 	{ "subl", emit_subaddand, &params_sub },
963 	{ "subq", emit_subaddand, &params_sub },
964 	{ "subss", emit_twobyte, &params_subss },
965 	{ "ucomiss", emit_twobyte, &params_ucomiss },
966 	{ "xorl",  emit_subaddand, &params_xor },
967 	{ "xorq",  emit_subaddand, &params_xor },
968 	{ NULL, NULL, NULL }
969 };
970 
opsort(const void * A,const void * B)971 static int opsort(const void* A, const void* B)
972 {
973 	const op_t* a = A;
974 	const op_t* b = B;
975 	return strcmp(a->mnemonic, b->mnemonic);
976 }
977 
getop(const char * n)978 static op_t* getop(const char* n)
979 {
980 #if 0
981 	op_t* o = ops;
982 	while(o->mnemonic)
983 	{
984 		if(!strcmp(o->mnemonic, n))
985 			return o;
986 		++o;
987 	}
988 
989 #else
990 	unsigned m, t, b;
991 	int r;
992 	t = sizeof(ops)/sizeof(ops[0])-1;
993 	b = 0;
994 
995 	while(b <= t)
996 	{
997 		m = ((t-b)>>1) + b;
998 		if((r = strcmp(ops[m].mnemonic, n)) == 0)
999 		{
1000 			return &ops[m];
1001 		}
1002 		else if(r < 0)
1003 		{
1004 			b = m + 1;
1005 		}
1006 		else
1007 		{
1008 			t = m - 1;
1009 		}
1010 	}
1011 #endif
1012 
1013 	return NULL;
1014 }
1015 
parsereg(const char * str)1016 static reg_t parsereg(const char* str)
1017 {
1018 	const char* s = str;
1019 	if(*s == 'a' && s[1] == 'l' && !s[2])
1020 	{
1021 		return R_AL;
1022 	}
1023 	else if(*s == 'a' && s[1] == 'x' && !s[2])
1024 	{
1025 		return R_AX;
1026 	}
1027 	if(*s == 'c' && s[1] == 'l' && !s[2])
1028 	{
1029 		return R_CL;
1030 	}
1031 	if(*s == 'x')
1032 	{
1033 		if(!strcmp(s, "xmm0"))
1034 			return R_XMM0;
1035 	}
1036 	else if(*s == 'r' && s[1])
1037 	{
1038 		++s;
1039 		if(s[1] == 'x')
1040 		{
1041 			switch(*s++)
1042 			{
1043 				case 'a': return R_RAX;
1044 				case 'b': return R_RBX;
1045 				case 'c': return R_RCX;
1046 				case 'd': return R_RDX;
1047 			}
1048 		}
1049 		else if(s[1] == 'i')
1050 		{
1051 			switch(*s++)
1052 			{
1053 				case 's': return R_RSI;
1054 				case 'd': return R_RDI;
1055 			}
1056 		}
1057 		else if(s[0] == 's' && s[1] == 'p' && !s[2])
1058 		{
1059 			return R_RSP;
1060 		}
1061 		else if(*s == '8' && !s[1])
1062 			return R_R8;
1063 		else if(*s == '9' && !s[1])
1064 			return R_R9;
1065 		else if(*s == '1' && s[1] == '0')
1066 			return R_R10;
1067 		else if(*s == '1' && s[1] == '5')
1068 			return R_R15;
1069 	}
1070 	else if(*s == 'e' && s[1])
1071 	{
1072 		++s;
1073 		if(s[1] == 'x')
1074 		{
1075 			switch(*s++)
1076 			{
1077 				case 'a': return R_EAX;
1078 				case 'b': return R_EBX;
1079 				case 'c': return R_ECX;
1080 				case 'd': return R_EDX;
1081 			}
1082 		}
1083 		else if(s[1] == 'i')
1084 		{
1085 			switch(*s++)
1086 			{
1087 				case 's': return R_ESI;
1088 				case 'd': return R_EDI;
1089 			}
1090 		}
1091 	}
1092 
1093 	crap("invalid register %s", str);
1094 
1095 	return 0;
1096 }
1097 
1098 typedef enum {
1099 	TOK_LABEL = 0x80,
1100 	TOK_INT = 0x81,
1101 	TOK_END = 0x82,
1102 	TOK_INVALID = 0x83,
1103 } token_t;
1104 
nexttok(const char ** str,char * label,u64 * val)1105 static unsigned char nexttok(const char** str, char* label, u64* val)
1106 {
1107 	const char* s = *str;
1108 
1109 	if(label) *label = 0;
1110 	if(val) *val = 0;
1111 
1112 	while(*s && *s == ' ') ++s;
1113 
1114 	if(!*s)
1115 	{
1116 		return TOK_END;
1117 	}
1118 	else if(*s == '$' || *s == '*' || *s == '%' || *s == '-' || *s == ')' || *s == '(' || *s == ',')
1119 	{
1120 		*str = s+1;
1121 		return *s;
1122 	}
1123 	else if(*s >= 'a' && *s <= 'z')
1124 	{
1125 		size_t a = strspn(s+1, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
1126 		if(a+1 >= LABELLEN)
1127 			crap("label %s too long", s);
1128 		if(label)
1129 		{
1130 			strncpy(label, s, a+1);
1131 			label[a+1] = 0;
1132 		}
1133 		*str = s+a+1;
1134 		return TOK_LABEL;
1135 	}
1136 	else if(*s >= '0' && *s <= '9')
1137 	{
1138 		char* endptr = NULL;
1139 		u64 v = strtol(s, &endptr, 0);
1140 		if(endptr && (endptr-s == 0))
1141 			crap("invalid integer %s", s);
1142 		if(val) *val = v;
1143 		*str = endptr;
1144 		return TOK_INT;
1145 	}
1146 	crap("can't parse '%s'", *str);
1147 	return TOK_INVALID;
1148 }
1149 
parsearg(const char ** str)1150 static arg_t parsearg(const char** str)
1151 {
1152 	arg_t arg;
1153 	const char* s = *str;
1154 	char label[20];
1155 	u64 val;
1156 	int negative = 1;
1157 	unsigned ttype;
1158 
1159 	arg.type = T_NONE;
1160 	arg.absolute = 0;
1161 
1162 	while(*s && *s == ' ') ++s;
1163 
1164 	switch(nexttok(&s, label, &val))
1165 	{
1166 		case '$' :
1167 			ttype = nexttok(&s, NULL, &val);
1168 			if(ttype == '-')
1169 			{
1170 				negative = -1;
1171 				ttype = nexttok(&s, NULL, &val);
1172 			}
1173 			if(ttype != TOK_INT)
1174 				crap("expected integer");
1175 			arg.type = T_IMMEDIATE;
1176 			arg.v.imm = negative * val;
1177 			break;
1178 		case '*' :
1179 			if((ttype = nexttok(&s, NULL, NULL)) != '%')
1180 			{
1181 				if(ttype == '(')
1182 					goto tok_memory;
1183 				crap("expected '%%'");
1184 			}
1185 			arg.absolute = 1;
1186 			/* fall through */
1187 		case '%' :
1188 			if(nexttok(&s, label, &val) != TOK_LABEL)
1189 				crap("expected label");
1190 			arg.type = T_REGISTER;
1191 			arg.v.reg = parsereg(label);
1192 			break;
1193 		case TOK_LABEL:
1194 			arg.type = T_LABEL;
1195 			strncpy(arg.v.label, label, LABELLEN);
1196 			break;
1197 		case '-':
1198 			negative = -1;
1199 			if(nexttok(&s, NULL, &val) != TOK_INT)
1200 				crap("expected integer");
1201 			/* fall through */
1202 		case TOK_INT:
1203 			if(nexttok(&s, label, NULL) != '(')
1204 				crap("expected '('"); // mov to/from fixed address not supported
1205 			/* fall through */
1206 		case '(':
1207 tok_memory:
1208 			arg.type = T_MEMORY;
1209 			arg.v.mem.indextype = T_NONE;
1210 			arg.v.mem.disp = negative * val;
1211 			ttype = nexttok(&s, label, &val);
1212 			if(ttype == '%' && nexttok(&s, label, &val) != TOK_LABEL)
1213 			{
1214 				crap("expected register");
1215 			}
1216 			if (ttype == '%')
1217 			{
1218 				arg.v.mem.basetype = T_REGISTER;
1219 				arg.v.mem.base.reg = parsereg(label);
1220 			}
1221 			else if (ttype == TOK_INT)
1222 			{
1223 				arg.v.mem.basetype = T_IMMEDIATE;
1224 				arg.v.mem.base.imm = val;
1225 			}
1226 			if((ttype = nexttok(&s, NULL, NULL)) == ',')
1227 			{
1228 				ttype = nexttok(&s, label, &val);
1229 				if(ttype == '%' && nexttok(&s, label, &val) != TOK_LABEL)
1230 				{
1231 					crap("expected register");
1232 				}
1233 				if (ttype == '%')
1234 				{
1235 					arg.v.mem.indextype = T_REGISTER;
1236 					arg.v.mem.index.reg = parsereg(label);
1237 				}
1238 				else if (ttype == TOK_INT)
1239 				{
1240 					crap("index must be register");
1241 					arg.v.mem.indextype = T_IMMEDIATE;
1242 					arg.v.mem.index.imm = val;
1243 				}
1244 				if(nexttok(&s, NULL, NULL) != ',')
1245 					crap("expected ','");
1246 				if(nexttok(&s, NULL, &val) != TOK_INT)
1247 					crap("expected integer");
1248 				if(val != 1 && val != 2 && val != 4 && val != 8)
1249 					crap("scale must 1, 2, 4 or 8");
1250 				arg.v.mem.scale = val;
1251 
1252 				ttype = nexttok(&s, NULL, NULL);
1253 			}
1254 			if(ttype != ')')
1255 			{
1256 				crap("expected ')' or ','");
1257 			}
1258 			break;
1259 		default:
1260 			crap("invalid token %hhu in %s", *(unsigned char*)s, *str);
1261 			break;
1262 	}
1263 
1264 	*str = s;
1265 
1266 	return arg;
1267 }
1268 
1269 /* ************************* */
1270 
assembler_init(int pass)1271 void assembler_init(int pass)
1272 {
1273 	compiledOfs = 0;
1274 	assembler_pass = pass;
1275 	if(!pass)
1276 	{
1277 		labelhash_free();
1278 		cur_line = NULL;
1279 	}
1280 	if(!ops_sorted)
1281 	{
1282 		ops_sorted = 1;
1283 		qsort(ops, sizeof(ops)/sizeof(ops[0])-1, sizeof(ops[0]), opsort);
1284 	}
1285 }
1286 
assembler_get_code_size(void)1287 size_t assembler_get_code_size(void)
1288 {
1289 	return compiledOfs;
1290 }
1291 
assembler_set_output(char * buf)1292 void assembler_set_output(char* buf)
1293 {
1294 	out = buf;
1295 }
1296 
assemble_line(const char * input,size_t len)1297 void assemble_line(const char* input, size_t len)
1298 {
1299 	char line[4096];
1300 	char* s;
1301 	op_t* o;
1302 	char* opn;
1303 	arg_t arg1, arg2;
1304 
1305 	arg1.type = T_NONE;
1306 	arg2.type = T_NONE;
1307 	opn = NULL;
1308 	o = NULL;
1309 
1310 	if(len < 1)
1311 		return;
1312 
1313 	if(len >= sizeof(line))
1314 		crap("line too long");
1315 
1316 	memcpy(line, input, sizeof(line));
1317 	cur_line = input;
1318 
1319 	if(line[len-1] == '\n') line[--len] = 0;
1320 	if(line[len-1] == ':')
1321 	{
1322 		line[--len] = 0;
1323 		if(assembler_pass)
1324 			debug("%s: 0x%x\n", line, compiledOfs);
1325 		else
1326 			hash_add_label(line, compiledOfs);
1327 	}
1328 	else
1329 	{
1330 		opn = line;
1331 		s = strchr(line, ' ');
1332 		if(s)
1333 		{
1334 			*s++ = 0;
1335 			arg1 = parsearg((const char**)&s);
1336 			if(*s)
1337 			{
1338 				if(*s != ',')
1339 					crap("expected ',', got '%c'", *s);
1340 				++s;
1341 				arg2 = parsearg((const char**)&s);
1342 			}
1343 		}
1344 
1345 		if(!opn)
1346 		{
1347 			crap("no operator in %s", line);
1348 		}
1349 
1350 		o = getop(opn);
1351 		if(!o)
1352 		{
1353 			crap("cannot handle op %s", opn);
1354 		}
1355 		o->func(opn, arg1, arg2, o->data);
1356 		if(assembler_pass)
1357 			debug("   - %s%s", cur_line, cur_line[strlen(cur_line)-1]=='\n'?"":"\n");
1358 	}
1359 }
1360 
1361 #ifdef SA_STANDALONE
main(int argc,char * argv[])1362 int main(int argc, char* argv[])
1363 {
1364 	char line[4096];
1365 	size_t len;
1366 	int pass;
1367 	FILE* file = NULL;
1368 
1369 	if(argc < 2)
1370 	{
1371 		crap("specify file");
1372 	}
1373 
1374 	file = fopen(argv[1], "r");
1375 	if(!file)
1376 	{
1377 		crap("can't open file");
1378 	}
1379 
1380 	if(argc > 2)
1381 	{
1382 		fout = fopen(argv[2], "w");
1383 		if(!fout)
1384 		{
1385 			crap("can't open %s for writing", argv[2]);
1386 		}
1387 	}
1388 
1389 	for(pass = 0; pass < 2; ++pass)
1390 	{
1391 		if(fseek(file, 0, SEEK_SET))
1392 			crap("can't rewind file");
1393 
1394 		if(pass)
1395 		{
1396 			char* b = malloc(assembler_get_code_size());
1397 			if(!b)
1398 				crap("cannot allocate memory");
1399 			assembler_set_output(b);
1400 		}
1401 
1402 		assembler_init(pass);
1403 
1404 		while(fgets(line, sizeof(line), file))
1405 		{
1406 			len = strlen(line);
1407 			if(!len) continue;
1408 
1409 			assemble_line(line, len);
1410 		}
1411 	}
1412 
1413 	assembler_init(0);
1414 
1415 	fclose(file);
1416 
1417 	return 0;
1418 }
1419 #endif
1420