static int pfpu_decode_insn(MilkymistPFPUState *s)

{

    uint32_t pc = s->regs[R_PC];

    uint32_t insn = s->microcode[pc];

    uint32_t reg_a = (insn >> 18) & 0x7f;

    uint32_t reg_b = (insn >> 11) & 0x7f;

    uint32_t op = (insn >> 7) & 0xf;

    uint32_t reg_d = insn & 0x7f;

    uint32_t r = 0;

    int latency = 0;



    switch (op) {

    case OP_NOP:

        break;

    case OP_FADD:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);

        float t = a + b;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_FADD;

        D_EXEC(qemu_log("ADD a=%f b=%f t=%f, r=%08x\n", a, b, t, r));

    } break;

    case OP_FSUB:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);

        float t = a - b;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_FSUB;

        D_EXEC(qemu_log("SUB a=%f b=%f t=%f, r=%08x\n", a, b, t, r));

    } break;

    case OP_FMUL:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);

        float t = a * b;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_FMUL;

        D_EXEC(qemu_log("MUL a=%f b=%f t=%f, r=%08x\n", a, b, t, r));

    } break;

    case OP_FABS:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float t = fabsf(a);

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_FABS;

        D_EXEC(qemu_log("ABS a=%f t=%f, r=%08x\n", a, t, r));

    } break;

    case OP_F2I:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        int32_t t = a;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_F2I;

        D_EXEC(qemu_log("F2I a=%f t=%d, r=%08x\n", a, t, r));

    } break;

    case OP_I2F:

    {

        int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]);

        float t = a;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_I2F;

        D_EXEC(qemu_log("I2F a=%08x t=%f, r=%08x\n", a, t, r));

    } break;

    case OP_VECTOUT:

    {

        uint32_t a = cpu_to_be32(s->gp_regs[reg_a]);

        uint32_t b = cpu_to_be32(s->gp_regs[reg_b]);

        target_phys_addr_t dma_ptr =

            get_dma_address(s->regs[R_MESHBASE],

                    s->gp_regs[GPR_X], s->gp_regs[GPR_Y]);

        cpu_physical_memory_write(dma_ptr, (uint8_t *)&a, 4);

        cpu_physical_memory_write(dma_ptr + 4, (uint8_t *)&b, 4);

        s->regs[R_LASTDMA] = dma_ptr + 4;

        D_EXEC(qemu_log("VECTOUT a=%08x b=%08x dma=%08x\n", a, b, dma_ptr));

        trace_milkymist_pfpu_vectout(a, b, dma_ptr);

    } break;

    case OP_SIN:

    {

        int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]);

        float t = sinf(a * (1.0f / (M_PI * 4096.0f)));

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_SIN;

        D_EXEC(qemu_log("SIN a=%d t=%f, r=%08x\n", a, t, r));

    } break;

    case OP_COS:

    {

        int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]);

        float t = cosf(a * (1.0f / (M_PI * 4096.0f)));

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_COS;

        D_EXEC(qemu_log("COS a=%d t=%f, r=%08x\n", a, t, r));

    } break;

    case OP_ABOVE:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);

        float t = (a > b) ? 1.0f : 0.0f;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_ABOVE;

        D_EXEC(qemu_log("ABOVE a=%f b=%f t=%f, r=%08x\n", a, b, t, r));

    } break;

    case OP_EQUAL:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);

        float t = (a == b) ? 1.0f : 0.0f;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_EQUAL;

        D_EXEC(qemu_log("EQUAL a=%f b=%f t=%f, r=%08x\n", a, b, t, r));

    } break;

    case OP_COPY:

    {

        r = s->gp_regs[reg_a];

        latency = LATENCY_COPY;

        D_EXEC(qemu_log("COPY"));

    } break;

    case OP_IF:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);

        uint32_t f = s->gp_regs[GPR_FLAGS];

        float t = (f != 0) ? a : b;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_IF;

        D_EXEC(qemu_log("IF f=%u a=%f b=%f t=%f, r=%08x\n", f, a, b, t, r));

    } break;

    case OP_TSIGN:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);

        float t = (b < 0) ? -a : a;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_TSIGN;

        D_EXEC(qemu_log("TSIGN a=%f b=%f t=%f, r=%08x\n", a, b, t, r));

    } break;

    case OP_QUAKE:

    {

        uint32_t a = s->gp_regs[reg_a];

        r = 0x5f3759df - (a >> 1);

        latency = LATENCY_QUAKE;

        D_EXEC(qemu_log("QUAKE a=%d r=%08x\n", a, r));

    } break;



    default:

        error_report("milkymist_pfpu: unknown opcode %d", op);

        break;

    }



    if (!reg_d) {

        D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d>\n",

                    s->regs[R_PC], opcode_to_str[op], reg_a, reg_b, latency,

                    s->regs[R_PC] + latency));

    } else {

        D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d> -> R%03d\n",

                    s->regs[R_PC], opcode_to_str[op], reg_a, reg_b, latency,

                    s->regs[R_PC] + latency, reg_d));

    }



    if (op == OP_VECTOUT) {

        return 0;

    }



    /* store output for this cycle */

    if (reg_d) {

        uint32_t val = output_queue_remove(s);

        D_EXEC(qemu_log("R%03d <- 0x%08x\n", reg_d, val));

        s->gp_regs[reg_d] = val;

    }



    output_queue_advance(s);



    /* store op output */

    if (op != OP_NOP) {

        output_queue_insert(s, r, latency-1);

    }



    /* advance PC */

    s->regs[R_PC]++;



    return 1;

};

static int pfpu_decode_insn(MilkymistPFPUState *s)

{

    uint32_t pc = s->regs[R_PC];

    uint32_t insn = s->microcode[pc];

    uint32_t reg_a = (insn >> 18) & 0x7f;

    uint32_t reg_b = (insn >> 11) & 0x7f;

    uint32_t op = (insn >> 7) & 0xf;

    uint32_t reg_d = insn & 0x7f;

    uint32_t r = 0;

    int latency = 0;



    switch (op) {

    case OP_NOP:

        break;

    case OP_FADD:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);

        float t = a + b;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_FADD;

        D_EXEC(qemu_log("ADD a=%f b=%f t=%f, r=%08x\n", a, b, t, r));

    } break;

    case OP_FSUB:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);

        float t = a - b;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_FSUB;

        D_EXEC(qemu_log("SUB a=%f b=%f t=%f, r=%08x\n", a, b, t, r));

    } break;

    case OP_FMUL:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);

        float t = a * b;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_FMUL;

        D_EXEC(qemu_log("MUL a=%f b=%f t=%f, r=%08x\n", a, b, t, r));

    } break;

    case OP_FABS:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float t = fabsf(a);

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_FABS;

        D_EXEC(qemu_log("ABS a=%f t=%f, r=%08x\n", a, t, r));

    } break;

    case OP_F2I:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        int32_t t = a;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_F2I;

        D_EXEC(qemu_log("F2I a=%f t=%d, r=%08x\n", a, t, r));

    } break;

    case OP_I2F:

    {

        int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]);

        float t = a;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_I2F;

        D_EXEC(qemu_log("I2F a=%08x t=%f, r=%08x\n", a, t, r));

    } break;

    case OP_VECTOUT:

    {

        uint32_t a = cpu_to_be32(s->gp_regs[reg_a]);

        uint32_t b = cpu_to_be32(s->gp_regs[reg_b]);

        target_phys_addr_t dma_ptr =

            get_dma_address(s->regs[R_MESHBASE],

                    s->gp_regs[GPR_X], s->gp_regs[GPR_Y]);

        cpu_physical_memory_write(dma_ptr, (uint8_t *)&a, 4);

        cpu_physical_memory_write(dma_ptr + 4, (uint8_t *)&b, 4);

        s->regs[R_LASTDMA] = dma_ptr + 4;

        D_EXEC(qemu_log("VECTOUT a=%08x b=%08x dma=%08x\n", a, b, dma_ptr));

        trace_milkymist_pfpu_vectout(a, b, dma_ptr);

    } break;

    case OP_SIN:

    {

        int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]);

        float t = sinf(a * (1.0f / (M_PI * 4096.0f)));

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_SIN;

        D_EXEC(qemu_log("SIN a=%d t=%f, r=%08x\n", a, t, r));

    } break;

    case OP_COS:

    {

        int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]);

        float t = cosf(a * (1.0f / (M_PI * 4096.0f)));

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_COS;

        D_EXEC(qemu_log("COS a=%d t=%f, r=%08x\n", a, t, r));

    } break;

    case OP_ABOVE:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);

        float t = (a > b) ? 1.0f : 0.0f;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_ABOVE;

        D_EXEC(qemu_log("ABOVE a=%f b=%f t=%f, r=%08x\n", a, b, t, r));

    } break;

    case OP_EQUAL:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);

        float t = (a == b) ? 1.0f : 0.0f;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_EQUAL;

        D_EXEC(qemu_log("EQUAL a=%f b=%f t=%f, r=%08x\n", a, b, t, r));

    } break;

    case OP_COPY:

    {

        r = s->gp_regs[reg_a];

        latency = LATENCY_COPY;

        D_EXEC(qemu_log("COPY"));

    } break;

    case OP_IF:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);

        uint32_t f = s->gp_regs[GPR_FLAGS];

        float t = (f != 0) ? a : b;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_IF;

        D_EXEC(qemu_log("IF f=%u a=%f b=%f t=%f, r=%08x\n", f, a, b, t, r));

    } break;

    case OP_TSIGN:

    {

        float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);

        float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);

        float t = (b < 0) ? -a : a;

        r = REINTERPRET_CAST(uint32_t, t);

        latency = LATENCY_TSIGN;

        D_EXEC(qemu_log("TSIGN a=%f b=%f t=%f, r=%08x\n", a, b, t, r));

    } break;

    case OP_QUAKE:

    {

        uint32_t a = s->gp_regs[reg_a];

        r = 0x5f3759df - (a >> 1);

        latency = LATENCY_QUAKE;

        D_EXEC(qemu_log("QUAKE a=%d r=%08x\n", a, r));

    } break;



    default:

        error_report("milkymist_pfpu: unknown opcode %d", op);

        break;

    }



    if (!reg_d) {

        D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d>\n",

                    s->regs[R_PC], opcode_to_str[op], reg_a, reg_b, latency,

                    s->regs[R_PC] + latency));

    } else {

        D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d> -> R%03d\n",

                    s->regs[R_PC], opcode_to_str[op], reg_a, reg_b, latency,

                    s->regs[R_PC] + latency, reg_d));

    }



    if (op == OP_VECTOUT) {

        return 0;

    }



    

    if (reg_d) {

        uint32_t val = output_queue_remove(s);

        D_EXEC(qemu_log("R%03d <- 0x%08x\n", reg_d, val));

        s->gp_regs[reg_d] = val;

    }



    output_queue_advance(s);



    

    if (op != OP_NOP) {

        output_queue_insert(s, r, latency-1);

    }



    

    s->regs[R_PC]++;



    return 1;

};

static int FUNC_0(MilkymistPFPUState *VAR_0)

{

    uint32_t pc = VAR_0->regs[R_PC];

    uint32_t insn = VAR_0->microcode[pc];

    uint32_t reg_a = (insn >> 18) & 0x7f;

    uint32_t reg_b = (insn >> 11) & 0x7f;

    uint32_t op = (insn >> 7) & 0xf;

    uint32_t reg_d = insn & 0x7f;

    uint32_t r = 0;

    int VAR_1 = 0;



    switch (op) {

    case OP_NOP:

        break;

    case OP_FADD:

    {

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]);

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_b]);

        float VAR_5 = VAR_5 + VAR_5;

        r = REINTERPRET_CAST(uint32_t, VAR_5);

        VAR_1 = LATENCY_FADD;

        D_EXEC(qemu_log("ADD VAR_5=%f VAR_5=%f VAR_5=%f, r=%08x\n", VAR_5, VAR_5, VAR_5, r));

    } break;

    case OP_FSUB:

    {

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]);

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_b]);

        float VAR_5 = VAR_5 - VAR_5;

        r = REINTERPRET_CAST(uint32_t, VAR_5);

        VAR_1 = LATENCY_FSUB;

        D_EXEC(qemu_log("SUB VAR_5=%f VAR_5=%f VAR_5=%f, r=%08x\n", VAR_5, VAR_5, VAR_5, r));

    } break;

    case OP_FMUL:

    {

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]);

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_b]);

        float VAR_5 = VAR_5 * VAR_5;

        r = REINTERPRET_CAST(uint32_t, VAR_5);

        VAR_1 = LATENCY_FMUL;

        D_EXEC(qemu_log("MUL VAR_5=%f VAR_5=%f VAR_5=%f, r=%08x\n", VAR_5, VAR_5, VAR_5, r));

    } break;

    case OP_FABS:

    {

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]);

        float VAR_5 = fabsf(VAR_5);

        r = REINTERPRET_CAST(uint32_t, VAR_5);

        VAR_1 = LATENCY_FABS;

        D_EXEC(qemu_log("ABS VAR_5=%f VAR_5=%f, r=%08x\n", VAR_5, VAR_5, r));

    } break;

    case OP_F2I:

    {

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]);

        int32_t VAR_5 = VAR_5;

        r = REINTERPRET_CAST(uint32_t, VAR_5);

        VAR_1 = LATENCY_F2I;

        D_EXEC(qemu_log("F2I VAR_5=%f VAR_5=%d, r=%08x\n", VAR_5, VAR_5, r));

    } break;

    case OP_I2F:

    {

        int32_t VAR_5 = REINTERPRET_CAST(int32_t, VAR_0->gp_regs[reg_a]);

        float VAR_5 = VAR_5;

        r = REINTERPRET_CAST(uint32_t, VAR_5);

        VAR_1 = LATENCY_I2F;

        D_EXEC(qemu_log("I2F VAR_5=%08x VAR_5=%f, r=%08x\n", VAR_5, VAR_5, r));

    } break;

    case OP_VECTOUT:

    {

        uint32_t VAR_5 = cpu_to_be32(VAR_0->gp_regs[reg_a]);

        uint32_t VAR_5 = cpu_to_be32(VAR_0->gp_regs[reg_b]);

        target_phys_addr_t dma_ptr =

            get_dma_address(VAR_0->regs[R_MESHBASE],

                    VAR_0->gp_regs[GPR_X], VAR_0->gp_regs[GPR_Y]);

        cpu_physical_memory_write(dma_ptr, (uint8_t *)&VAR_5, 4);

        cpu_physical_memory_write(dma_ptr + 4, (uint8_t *)&VAR_5, 4);

        VAR_0->regs[R_LASTDMA] = dma_ptr + 4;

        D_EXEC(qemu_log("VECTOUT VAR_5=%08x VAR_5=%08x dma=%08x\n", VAR_5, VAR_5, dma_ptr));

        trace_milkymist_pfpu_vectout(VAR_5, VAR_5, dma_ptr);

    } break;

    case OP_SIN:

    {

        int32_t VAR_5 = REINTERPRET_CAST(int32_t, VAR_0->gp_regs[reg_a]);

        float VAR_5 = sinf(VAR_5 * (1.0f / (M_PI * 4096.0f)));

        r = REINTERPRET_CAST(uint32_t, VAR_5);

        VAR_1 = LATENCY_SIN;

        D_EXEC(qemu_log("SIN VAR_5=%d VAR_5=%f, r=%08x\n", VAR_5, VAR_5, r));

    } break;

    case OP_COS:

    {

        int32_t VAR_5 = REINTERPRET_CAST(int32_t, VAR_0->gp_regs[reg_a]);

        float VAR_5 = cosf(VAR_5 * (1.0f / (M_PI * 4096.0f)));

        r = REINTERPRET_CAST(uint32_t, VAR_5);

        VAR_1 = LATENCY_COS;

        D_EXEC(qemu_log("COS VAR_5=%d VAR_5=%f, r=%08x\n", VAR_5, VAR_5, r));

    } break;

    case OP_ABOVE:

    {

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]);

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_b]);

        float VAR_5 = (VAR_5 > VAR_5) ? 1.0f : 0.0f;

        r = REINTERPRET_CAST(uint32_t, VAR_5);

        VAR_1 = LATENCY_ABOVE;

        D_EXEC(qemu_log("ABOVE VAR_5=%f VAR_5=%f VAR_5=%f, r=%08x\n", VAR_5, VAR_5, VAR_5, r));

    } break;

    case OP_EQUAL:

    {

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]);

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_b]);

        float VAR_5 = (VAR_5 == VAR_5) ? 1.0f : 0.0f;

        r = REINTERPRET_CAST(uint32_t, VAR_5);

        VAR_1 = LATENCY_EQUAL;

        D_EXEC(qemu_log("EQUAL VAR_5=%f VAR_5=%f VAR_5=%f, r=%08x\n", VAR_5, VAR_5, VAR_5, r));

    } break;

    case OP_COPY:

    {

        r = VAR_0->gp_regs[reg_a];

        VAR_1 = LATENCY_COPY;

        D_EXEC(qemu_log("COPY"));

    } break;

    case OP_IF:

    {

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]);

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_b]);

        uint32_t f = VAR_0->gp_regs[GPR_FLAGS];

        float VAR_5 = (f != 0) ? VAR_5 : VAR_5;

        r = REINTERPRET_CAST(uint32_t, VAR_5);

        VAR_1 = LATENCY_IF;

        D_EXEC(qemu_log("IF f=%u VAR_5=%f VAR_5=%f VAR_5=%f, r=%08x\n", f, VAR_5, VAR_5, VAR_5, r));

    } break;

    case OP_TSIGN:

    {

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]);

        float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_b]);

        float VAR_5 = (VAR_5 < 0) ? -VAR_5 : VAR_5;

        r = REINTERPRET_CAST(uint32_t, VAR_5);

        VAR_1 = LATENCY_TSIGN;

        D_EXEC(qemu_log("TSIGN VAR_5=%f VAR_5=%f VAR_5=%f, r=%08x\n", VAR_5, VAR_5, VAR_5, r));

    } break;

    case OP_QUAKE:

    {

        uint32_t VAR_5 = VAR_0->gp_regs[reg_a];

        r = 0x5f3759df - (VAR_5 >> 1);

        VAR_1 = LATENCY_QUAKE;

        D_EXEC(qemu_log("QUAKE VAR_5=%d r=%08x\n", VAR_5, r));

    } break;



    default:

        error_report("milkymist_pfpu: unknown opcode %d", op);

        break;

    }



    if (!reg_d) {

        D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d>\n",

                    VAR_0->regs[R_PC], opcode_to_str[op], reg_a, reg_b, VAR_1,

                    VAR_0->regs[R_PC] + VAR_1));

    } else {

        D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d> -> R%03d\n",

                    VAR_0->regs[R_PC], opcode_to_str[op], reg_a, reg_b, VAR_1,

                    VAR_0->regs[R_PC] + VAR_1, reg_d));

    }



    if (op == OP_VECTOUT) {

        return 0;

    }



    

    if (reg_d) {

        uint32_t val = output_queue_remove(VAR_0);

        D_EXEC(qemu_log("R%03d <- 0x%08x\n", reg_d, val));

        VAR_0->gp_regs[reg_d] = val;

    }



    output_queue_advance(VAR_0);



    

    if (op != OP_NOP) {

        output_queue_insert(VAR_0, r, VAR_1-1);

    }



    

    VAR_0->regs[R_PC]++;



    return 1;

};

static int FUNC_0(MilkymistPFPUState *VAR_0)
{ uint32_t pc = VAR_0->regs[R_PC]; uint32_t insn = VAR_0->microcode[pc]; uint32_t reg_a = (insn >> 18) & 0x7f; uint32_t reg_b = (insn >> 11) & 0x7f; uint32_t op = (insn >> 7) & 0xf; uint32_t reg_d = insn & 0x7f; uint32_t r = 0; int VAR_1 = 0; switch (op) { case OP_NOP:
break; case OP_FADD:
{ float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]); float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_b]); float VAR_5 = VAR_5 + VAR_5; r = REINTERPRET_CAST(uint32_t, VAR_5); VAR_1 = LATENCY_FADD; D_EXEC(qemu_log("ADD VAR_5=%f VAR_5=%f VAR_5=%f, r=%08x\n", VAR_5, VAR_5, VAR_5, r)); } break; case OP_FSUB:
{ float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]); float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_b]); float VAR_5 = VAR_5 - VAR_5; r = REINTERPRET_CAST(uint32_t, VAR_5); VAR_1 = LATENCY_FSUB; D_EXEC(qemu_log("SUB VAR_5=%f VAR_5=%f VAR_5=%f, r=%08x\n", VAR_5, VAR_5, VAR_5, r)); } break; case OP_FMUL:
{ float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]); float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_b]); float VAR_5 = VAR_5 * VAR_5; r = REINTERPRET_CAST(uint32_t, VAR_5); VAR_1 = LATENCY_FMUL; D_EXEC(qemu_log("MUL VAR_5=%f VAR_5=%f VAR_5=%f, r=%08x\n", VAR_5, VAR_5, VAR_5, r)); } break; case OP_FABS:
{ float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]); float VAR_5 = fabsf(VAR_5); r = REINTERPRET_CAST(uint32_t, VAR_5); VAR_1 = LATENCY_FABS; D_EXEC(qemu_log("ABS VAR_5=%f VAR_5=%f, r=%08x\n", VAR_5, VAR_5, r)); } break; case OP_F2I:
{ float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]); int32_t VAR_5 = VAR_5; r = REINTERPRET_CAST(uint32_t, VAR_5); VAR_1 = LATENCY_F2I; D_EXEC(qemu_log("F2I VAR_5=%f VAR_5=%d, r=%08x\n", VAR_5, VAR_5, r)); } break; case OP_I2F:
{ int32_t VAR_5 = REINTERPRET_CAST(int32_t, VAR_0->gp_regs[reg_a]); float VAR_5 = VAR_5; r = REINTERPRET_CAST(uint32_t, VAR_5); VAR_1 = LATENCY_I2F; D_EXEC(qemu_log("I2F VAR_5=%08x VAR_5=%f, r=%08x\n", VAR_5, VAR_5, r)); } break; case OP_VECTOUT:
{ uint32_t VAR_5 = cpu_to_be32(VAR_0->gp_regs[reg_a]); uint32_t VAR_5 = cpu_to_be32(VAR_0->gp_regs[reg_b]); target_phys_addr_t dma_ptr =
get_dma_address(VAR_0->regs[R_MESHBASE],
VAR_0->gp_regs[GPR_X], VAR_0->gp_regs[GPR_Y]); cpu_physical_memory_write(dma_ptr, (uint8_t *)&VAR_5, 4); cpu_physical_memory_write(dma_ptr + 4, (uint8_t *)&VAR_5, 4); VAR_0->regs[R_LASTDMA] = dma_ptr + 4; D_EXEC(qemu_log("VECTOUT VAR_5=%08x VAR_5=%08x dma=%08x\n", VAR_5, VAR_5, dma_ptr)); trace_milkymist_pfpu_vectout(VAR_5, VAR_5, dma_ptr); } break; case OP_SIN:
{ int32_t VAR_5 = REINTERPRET_CAST(int32_t, VAR_0->gp_regs[reg_a]); float VAR_5 = sinf(VAR_5 * (1.0f / (M_PI * 4096.0f))); r = REINTERPRET_CAST(uint32_t, VAR_5); VAR_1 = LATENCY_SIN; D_EXEC(qemu_log("SIN VAR_5=%d VAR_5=%f, r=%08x\n", VAR_5, VAR_5, r)); } break; case OP_COS:
{ int32_t VAR_5 = REINTERPRET_CAST(int32_t, VAR_0->gp_regs[reg_a]); float VAR_5 = cosf(VAR_5 * (1.0f / (M_PI * 4096.0f))); r = REINTERPRET_CAST(uint32_t, VAR_5); VAR_1 = LATENCY_COS; D_EXEC(qemu_log("COS VAR_5=%d VAR_5=%f, r=%08x\n", VAR_5, VAR_5, r)); } break; case OP_ABOVE:
{ float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]); float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_b]); float VAR_5 = (VAR_5 > VAR_5) ? 1.0f : 0.0f; r = REINTERPRET_CAST(uint32_t, VAR_5); VAR_1 = LATENCY_ABOVE; D_EXEC(qemu_log("ABOVE VAR_5=%f VAR_5=%f VAR_5=%f, r=%08x\n", VAR_5, VAR_5, VAR_5, r)); } break; case OP_EQUAL:
{ float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]); float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_b]); float VAR_5 = (VAR_5 == VAR_5) ? 1.0f : 0.0f; r = REINTERPRET_CAST(uint32_t, VAR_5); VAR_1 = LATENCY_EQUAL; D_EXEC(qemu_log("EQUAL VAR_5=%f VAR_5=%f VAR_5=%f, r=%08x\n", VAR_5, VAR_5, VAR_5, r)); } break; case OP_COPY:
{ r = VAR_0->gp_regs[reg_a]; VAR_1 = LATENCY_COPY; D_EXEC(qemu_log("COPY")); } break; case OP_IF:
{ float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]); float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_b]); uint32_t f = VAR_0->gp_regs[GPR_FLAGS]; float VAR_5 = (f != 0) ? VAR_5 : VAR_5; r = REINTERPRET_CAST(uint32_t, VAR_5); VAR_1 = LATENCY_IF; D_EXEC(qemu_log("IF f=%u VAR_5=%f VAR_5=%f VAR_5=%f, r=%08x\n", f, VAR_5, VAR_5, VAR_5, r)); } break; case OP_TSIGN:
{ float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_a]); float VAR_5 = REINTERPRET_CAST(float, VAR_0->gp_regs[reg_b]); float VAR_5 = (VAR_5 < 0) ? -VAR_5 : VAR_5; r = REINTERPRET_CAST(uint32_t, VAR_5); VAR_1 = LATENCY_TSIGN; D_EXEC(qemu_log("TSIGN VAR_5=%f VAR_5=%f VAR_5=%f, r=%08x\n", VAR_5, VAR_5, VAR_5, r)); } break; case OP_QUAKE:
{ uint32_t VAR_5 = VAR_0->gp_regs[reg_a]; r = 0x5f3759df - (VAR_5 >> 1); VAR_1 = LATENCY_QUAKE; D_EXEC(qemu_log("QUAKE VAR_5=%d r=%08x\n", VAR_5, r)); } break; default:
error_report("milkymist_pfpu: unknown opcode %d", op); break; } if (!reg_d) { D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d>\n",
VAR_0->regs[R_PC], opcode_to_str[op], reg_a, reg_b, VAR_1,
VAR_0->regs[R_PC] + VAR_1)); } else { D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d> -> R%03d\n",
VAR_0->regs[R_PC], opcode_to_str[op], reg_a, reg_b, VAR_1,
VAR_0->regs[R_PC] + VAR_1, reg_d)); } if (op == OP_VECTOUT) { return 0; } if (reg_d) { uint32_t val = output_queue_remove(VAR_0); D_EXEC(qemu_log("R%03d <- 0x%08x\n", reg_d, val)); VAR_0->gp_regs[reg_d] = val; } output_queue_advance(VAR_0); if (op != OP_NOP) { output_queue_insert(VAR_0, r, VAR_1-1); } VAR_0->regs[R_PC]++; return 1; };