typedef enum
|
typedef enum
|
{
|
{
|
LODI,
|
LODI,
|
STO,
|
STO,
|
ADDI,
|
ADDI,
|
ADD,
|
ADD,
|
SUBI,
|
SUBI,
|
SUB,
|
SUB,
|
MULI,
|
MULI,
|
MUL,
|
MUL,
|
DIVI,
|
DIVI,
|
DIV,
|
DIV,
|
INC,
|
INC,
|
DEC
|
DEC
|
} INSN;
|
} INSN;
|
|
|
f (pc)
|
f (pc)
|
short *pc;
|
short *pc;
|
{
|
{
|
long long stack[16], *sp = &stack[16], acc = 0;
|
long long stack[16], *sp = &stack[16], acc = 0;
|
|
|
for (;;)
|
for (;;)
|
{
|
{
|
switch ((INSN)*pc++)
|
switch ((INSN)*pc++)
|
{
|
{
|
case LODI:
|
case LODI:
|
*--sp = acc;
|
*--sp = acc;
|
acc = ((long long)*pc++) << 32;
|
acc = ((long long)*pc++) << 32;
|
break;
|
break;
|
case STO:
|
case STO:
|
return (acc >> 32) + (((((unsigned long long) acc) & 0xffffffff) & (1 << 31)) != 0);
|
return (acc >> 32) + (((((unsigned long long) acc) & 0xffffffff) & (1 << 31)) != 0);
|
break;
|
break;
|
case ADDI:
|
case ADDI:
|
acc += ((long long)*pc++) << 32;
|
acc += ((long long)*pc++) << 32;
|
break;
|
break;
|
case ADD:
|
case ADD:
|
acc = *sp++ + acc;
|
acc = *sp++ + acc;
|
break;
|
break;
|
case SUBI:
|
case SUBI:
|
acc -= ((long long)*pc++) << 32;
|
acc -= ((long long)*pc++) << 32;
|
break;
|
break;
|
case SUB:
|
case SUB:
|
acc = *sp++ - acc;
|
acc = *sp++ - acc;
|
break;
|
break;
|
case MULI:
|
case MULI:
|
acc *= *pc++;
|
acc *= *pc++;
|
break;
|
break;
|
case MUL:
|
case MUL:
|
{
|
{
|
long long aux;
|
long long aux;
|
unsigned char minus;
|
unsigned char minus;
|
|
|
minus = 0;
|
minus = 0;
|
aux = *sp++;
|
aux = *sp++;
|
if (aux < 0)
|
if (aux < 0)
|
{
|
{
|
minus = ~minus;
|
minus = ~minus;
|
aux = -aux;
|
aux = -aux;
|
}
|
}
|
if (acc < 0)
|
if (acc < 0)
|
{
|
{
|
minus = ~minus;
|
minus = ~minus;
|
acc = -acc;
|
acc = -acc;
|
}
|
}
|
acc = ((((((unsigned long long) acc) & 0xffffffff) * (((unsigned long long) aux) & 0xffffffff)) >> 32)
|
acc = ((((((unsigned long long) acc) & 0xffffffff) * (((unsigned long long) aux) & 0xffffffff)) >> 32)
|
+ ((((unsigned long long) acc) >> 32) * (((unsigned long long) aux) & 0xffffffff) + (((unsigned long long) acc) & 0xffffffff) + (((unsigned long long) aux) >> 32))
|
+ ((((unsigned long long) acc) >> 32) * (((unsigned long long) aux) & 0xffffffff) + (((unsigned long long) acc) & 0xffffffff) + (((unsigned long long) aux) >> 32))
|
+ (((((unsigned long long) acc) >> 32) * (((unsigned long long) aux) >> 32)) << 32));
|
+ (((((unsigned long long) acc) >> 32) * (((unsigned long long) aux) >> 32)) << 32));
|
if (minus)
|
if (minus)
|
acc = -acc;
|
acc = -acc;
|
}
|
}
|
break;
|
break;
|
case DIVI:
|
case DIVI:
|
{
|
{
|
short aux;
|
short aux;
|
|
|
aux = *pc++;
|
aux = *pc++;
|
acc = (acc + aux / 2) / aux;
|
acc = (acc + aux / 2) / aux;
|
}
|
}
|
break;
|
break;
|
case DIV:
|
case DIV:
|
{
|
{
|
long long aux;
|
long long aux;
|
unsigned char minus;
|
unsigned char minus;
|
|
|
minus = 0;
|
minus = 0;
|
aux = *sp++;
|
aux = *sp++;
|
if (aux < 0)
|
if (aux < 0)
|
{
|
{
|
minus = ~minus;
|
minus = ~minus;
|
aux = -aux;
|
aux = -aux;
|
}
|
}
|
if (acc < 0)
|
if (acc < 0)
|
{
|
{
|
minus = ~minus;
|
minus = ~minus;
|
acc = -acc;
|
acc = -acc;
|
}
|
}
|
|
|
if (((unsigned long long)acc) == 0)
|
if (((unsigned long long)acc) == 0)
|
acc = (unsigned long long)-1 / 2;
|
acc = (unsigned long long)-1 / 2;
|
else if ((((unsigned long long) ((unsigned long long)acc)) & 0xffffffff) == 0)
|
else if ((((unsigned long long) ((unsigned long long)acc)) & 0xffffffff) == 0)
|
acc = ((unsigned long long)aux) / (((unsigned long long) ((unsigned long long)acc)) >> 32);
|
acc = ((unsigned long long)aux) / (((unsigned long long) ((unsigned long long)acc)) >> 32);
|
else if ((((unsigned long long) ((unsigned long long)acc)) >> 32) == 0)
|
else if ((((unsigned long long) ((unsigned long long)acc)) >> 32) == 0)
|
acc = ((((unsigned long long)aux) / ((unsigned long long)acc)) << 32)
|
acc = ((((unsigned long long)aux) / ((unsigned long long)acc)) << 32)
|
+ ((((unsigned long long)aux) % ((unsigned long long)acc)) << 32) / ((unsigned long long)acc);
|
+ ((((unsigned long long)aux) % ((unsigned long long)acc)) << 32) / ((unsigned long long)acc);
|
else
|
else
|
{
|
{
|
unsigned char shift;
|
unsigned char shift;
|
unsigned long hi;
|
unsigned long hi;
|
|
|
shift = 32;
|
shift = 32;
|
hi = (((unsigned long long) ((unsigned long long)acc)) >> 32);
|
hi = (((unsigned long long) ((unsigned long long)acc)) >> 32);
|
do {
|
do {
|
if (hi & ((unsigned long)1 << (shift - 1)))
|
if (hi & ((unsigned long)1 << (shift - 1)))
|
break;
|
break;
|
} while (--shift != 0);
|
} while (--shift != 0);
|
printf("shift = %d\n", shift);
|
printf("shift = %d\n", shift);
|
acc = ((((unsigned long long)aux) / ((unsigned long long)acc)) << 32)
|
acc = ((((unsigned long long)aux) / ((unsigned long long)acc)) << 32)
|
+ (((((unsigned long long)aux) % ((unsigned long long)acc)) << (32 - shift)) + ((((unsigned long long)acc) >> shift) / 2)) / (((unsigned long long)acc) >> shift);
|
+ (((((unsigned long long)aux) % ((unsigned long long)acc)) << (32 - shift)) + ((((unsigned long long)acc) >> shift) / 2)) / (((unsigned long long)acc) >> shift);
|
}
|
}
|
|
|
if (minus)
|
if (minus)
|
acc = -acc;
|
acc = -acc;
|
}
|
}
|
break;
|
break;
|
case INC:
|
case INC:
|
acc += 1;
|
acc += 1;
|
break;
|
break;
|
case DEC:
|
case DEC:
|
acc -= 1;
|
acc -= 1;
|
break;
|
break;
|
}
|
}
|
printf("%08lx.%08lx\n", (long)(((unsigned long long) acc) >> 32) , (long)(((unsigned long long) acc) & 0xffffffff));
|
printf("%08lx.%08lx\n", (long)(((unsigned long long) acc) >> 32) , (long)(((unsigned long long) acc) & 0xffffffff));
|
}
|
}
|
}
|
}
|
|
|