/* When you assign just one register to dword(), the second one is
 * automatically extended to hold the higher dword bits. */

/* parametry: DWORD (ax,dx), DWORD (bx,cx), si */
/* vraci DWORD (ax,dx) ; zbytek == garbage */
/* si ma po navratu z funkce puvodni hodnotu */
void
0x17e(uint32_t dword1 /* ax,dx */, uint32_t dword2 /* bx,cx */, uint16_t something /* si */)
{
	low16(dword1) *= low16(dword2);
	high16(dword1) = (high16(dword2) * low16(dword1) + high16(dword1) * low16(dword2));
	high16(dword1) += something;
}

void
0x262()
{
	if (cl >= 0x10) {
		cl -= 0x10;
		dx = ax << cl;
		ax = 0;
	} else {
		bx = ax;
		ax = ax << cl;
		dx = dx << cl;

		cl = 0x10 - cl;
		bx = bx >> cl;
		dx |= bx;
	}
}

void
0x283()
{
	if (cl >= 0x10) {
		cl -= 0x10;
		xchg(ax, dx);
		dx = extend_dword(ax);
		ax >>= cl;
	} else {
		bx = dx;
		ax >>= cl;
		dx >>= cl;

		cl = 0x10 - cl;
		bx <<= cl;
		ax |= bx;
	}
}

void
function()
{
	uint32_t tmp_dword1, tmp_dword2, tmp_dword3;

	enter();

	save(si);

	ax = *(bp + 0x6);
	ax &= 0xf;
	*(bp - 0x6) = ax;

	/* XXX: Mozna jsem v tehle dvou assignmentech popletl poradi
	 * registru v dwordech, potreba zkontrolovat! */

	dword(cx, bx) = dword(*(bp + 0xc), *(bp + 0xe)) + ax;
	dword(ax, dx) = dword(*(bp + 0xe), *(bp + 0x10)) + *(bp - 0x6);

	((void *()) 0x17e)();

	/* Tohle vypada tak hashovite ;-)). */
	dword(cx, bx) = dword((*bp + 0xa), *(bp + 0xc));
	dword(cx, bx) += dword((*bp + 0xe), *(bp + 0x10));
	dword(cx, bx) += dword((*bp + 0x12), *(bp + 0x14));
	dword(cx, bx) += dword((*bp + 0x6), *(bp + 0x8));
	dword(cx, bx) += dword(ax, dx);

	dword(ax, dx) = *(bp - 0x6);

	si = *(bp + 0x14);

	tmp_dword1 = dword(cx, bx);

	dword(bx, si) = *(bp + 0x12) + dword(ax, dx);
	/* nemuzu vyoptimalizovat, protoze odporne SI ovlivnuje 0x17e */
	dword(cx, bx) = dword(bx, si);

	dword(ax, dx) = *(bp - 0x6) + dword(*(bp + 0x6), *(bp + 0x8));
	
	((void *()) 0x17e)();

	dword(cx, bx) = tmp_dword1 + dword(ax, dx);

	dword(*(bp - 0x4), *(bp - 0x2)) = dword(cx, bx);
	dword(ax, dx) = dword(*(bp - 0x4), *(bp - 0x2));

	cl = *(bp - 0x6);
	((void *()) 0x262)(); /* huh, to je nejake divne ;-) */

	dword(cx, bx) = dword(ax, dx) + dword(*(bp - 0x4), *(bp - 0x2));
	dword(ax, dx) = dword(*(bp - 0xa), *(bp - 0xc));

	tmp_dword1 = dword(cx, bx);

	cl = 0x7;
	((void *()) 0x262)(); /* huh, to je nejake divne ;-) */

	dword(cx, bx) = tmp_dword1 + dword(ax, dx);

	dword(ax, dx) = dword(*(bp + 0x12), *(bp + 0x14));

	tmp_dword1 = dword(cx, bx);

	cl = 0xb;
	((void *()) 0x262)(); /* huh, to je nejake divne ;-) */

	dword(cx, bx) = tmp_dword1 + dword(ax, dx);
	
	dword(ax, dx) = dword(*(bp + 0xe), *(bp + 0x10));

	tmp_dword1 = dword(cx, bx);

	cl = 0x11;
	((void *()) 0x262)(); /* huh, to je nejake divne ;-) */

	dword(cx, bx) = tmp_dword1 + dword(ax, dx);
	
	dword(ax, dx) = dword(*(bp - 0x4), *(bp + 0x2));

	cl = 0xd;
	((void *()) 0x262)(); /* huh, to je nejake divne ;-) */

	tmp_dword1 = dword(ax, dx);
	
	dword(ax, dx) = dword(*(bp - 0x4), *(bp + 0x2));

	cl = 0xf;
	((void *()) 0x283)(); /* huh, to je take nejake divne ;-) */

	dword(cx, bx) = tmp_dword1 + dword(ax, dx);

	dword(*(bp - 0x4), *(bp - 0x2)) = dword(cx, bx);

	/* Drop the sign. */
	*(bp - 0x4) &= 0xffff;
	*(bp - 0x2) &= 0x7fff;

	/* ? */
	*(bp - 0x4) |= 0x0;
	*(bp - 0x2) |= 0x4000;

	dword(ax, dx) = dword(*(bp - 0x4), *(bp - 0x2));

	goto _3528;
_3528:
	load(si);

	leave();
}
