#include <stdint.h>

#define enter()
#define save(x)
#define load(x)
#define leave()

/* 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) */
/* vraci DWORD (ax,dx) ; zbytek == garbage */
/* si ma po navratu z funkce puvodni hodnotu */
uint32_t
f_0x17e(uint32_t dword1 /* ax,dx */, uint32_t dword2 /* cx,bx */)
{
	/* [0] == lower, [1] == higher */
	uint16_t dword1W[2] = &dword1, dword2W[2] = &dword2;

	dword1W[0] = dword1W[0]              *              dword2W[1];
	dword1W[1] = dword1W[0] * dword2W[0] + dword1W[1] * dword2W[1];

	return dword1;
}

void
function(unsigned char *bp)
{
	uint16_t *bp_m_0x6 = bp - 0x6;
	uint32_t axdx_dword, cxbx_dword;

	enter();

	save(si);

	*bp_m_0x6 = *(bp + 0x6) & 0xf;

	dword_cxbx = *((uint32_t) (bp + 0xc)) + *bp_m_0x6;
	dword_axdx = *((uint32_t) (bp + 0xe)) + *bp_m_0x6;

	/* Tohle vypada tak hashovite ;-)). */
	dword_cxbx = f_0x17e(dword_axdx, dword_cxbx)
		      + si << 0x10;
		      + *((uint32_t) (bp + 0x6))
		      + *((uint32_t) (bp + 0xa))
		      + *((uint32_t) (bp + 0xe))
		      + *((uint32_t) (bp + 0x12));
	dword_cxbx += f_0x17e(*bp_m_0x6 + *((uint32_t) (bp + 0x6)),
			      *bp_m_0x6 + *((uint32_t) (bp + 0x12)))
			 + *((uint16_t) (bp + 0x12));
	*((uint32_t *) (bp - 0x4)) = dword_cxbx;
	dword_cxbx += dword_cxbx << *bp_m_0x6;
	dword_cxbx += *((uint32_t) (bp - 0xc)) << 0x7;
	dword_cxbx += *((uint32_t) (bp + 0x12)) << 0xb;
	dword_cxbx += *((uint32_t) (bp + 0xe)) << 0x11;
	dword_cxbx += *((uint32_t) (bp - 0x4)) << 0xd;
	dword_cxbx += *((uint32_t) (bp - 0x4)) >> 0xf;

	/* we're low-endian, remember */
	*((uint32_t) (bp - 0x4)) = dword_cxbx & 0x7fffffff | 0x40000000;

	dword_axdx = *((uint32_t) (bp - 0x4));

	goto _3528;
_3528:
	load(si);

	leave();
}
