//
// Initialization of the info structure per instruction
//
void microblazeGenInstructionInfo (microblazeInstructionInfoP info, Uns64 instruction) {
    info->opcode = opcode[info->type];
    switch (info->type) {
        case MICROBLAZE_IT_ADD_TYPEA1:
        case MICROBLAZE_IT_ADDC_TYPEA1:
        case MICROBLAZE_IT_ADDK_TYPEA1:
        case MICROBLAZE_IT_ADDKC_TYPEA1:
        case MICROBLAZE_IT_AND_TYPEA1:
        case MICROBLAZE_IT_ANDN_TYPEA1:
        case MICROBLAZE_IT_FADD_TYPEA1:
        case MICROBLAZE_IT_FCMPEQ_TYPEA1:
        case MICROBLAZE_IT_FCMPGE_TYPEA1:
        case MICROBLAZE_IT_FCMPGT_TYPEA1:
        case MICROBLAZE_IT_FCMPLE_TYPEA1:
        case MICROBLAZE_IT_FCMPLT_TYPEA1:
        case MICROBLAZE_IT_FCMPNE_TYPEA1:
        case MICROBLAZE_IT_FCMPUN_TYPEA1:
        case MICROBLAZE_IT_FDIV_TYPEA1:
        case MICROBLAZE_IT_FMUL_TYPEA1:
        case MICROBLAZE_IT_FRSUB_TYPEA1:
        case MICROBLAZE_IT_LWX_TYPEA1:
        case MICROBLAZE_IT_MUL_TYPEA1:
        case MICROBLAZE_IT_MULH_TYPEA1:
        case MICROBLAZE_IT_MULHSU_TYPEA1:
        case MICROBLAZE_IT_MULHU_TYPEA1:
        case MICROBLAZE_IT_OR_TYPEA1:
        case MICROBLAZE_IT_PCMPBF_TYPEA1:
        case MICROBLAZE_IT_PCMPEQ_TYPEA1:
        case MICROBLAZE_IT_PCMPNE_TYPEA1:
        case MICROBLAZE_IT_RSUB_TYPEA1:
        case MICROBLAZE_IT_RSUBC_TYPEA1:
        case MICROBLAZE_IT_RSUBK_TYPEA1:
        case MICROBLAZE_IT_RSUBKC_TYPEA1:
        case MICROBLAZE_IT_SWX_TYPEA1:
        case MICROBLAZE_IT_XOR_TYPEA1:
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            info->rB = VECINDEX(instruction,15,11,0); // 15:11
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            break;

        case MICROBLAZE_IT_BEQ_TYPEA2:
        case MICROBLAZE_IT_BEQD_TYPEA2:
        case MICROBLAZE_IT_BGE_TYPEA2:
        case MICROBLAZE_IT_BGED_TYPEA2:
        case MICROBLAZE_IT_BGT_TYPEA2:
        case MICROBLAZE_IT_BGTD_TYPEA2:
        case MICROBLAZE_IT_BLE_TYPEA2:
        case MICROBLAZE_IT_BLED_TYPEA2:
        case MICROBLAZE_IT_BLT_TYPEA2:
        case MICROBLAZE_IT_BLTD_TYPEA2:
        case MICROBLAZE_IT_BNE_TYPEA2:
        case MICROBLAZE_IT_BNED_TYPEA2:
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            info->rB = VECINDEX(instruction,15,11,0); // 15:11
            break;

        case MICROBLAZE_IT_BR_TYPEA3:
        case MICROBLAZE_IT_BRA_TYPEA3:
        case MICROBLAZE_IT_BRAD_TYPEA3:
        case MICROBLAZE_IT_BRD_TYPEA3:
            info->rB = VECINDEX(instruction,15,11,0); // 15:11
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            break;

        case MICROBLAZE_IT_BRALD_TYPEA4:
        case MICROBLAZE_IT_BRLD_TYPEA4:
            info->rB = VECINDEX(instruction,15,11,0); // 15:11
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            break;

        case MICROBLAZE_IT_BRK_TYPEA5:
            info->rB = VECINDEX(instruction,15,11,0); // 15:11
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            break;

        case MICROBLAZE_IT_BSLL_TYPEA6:
        case MICROBLAZE_IT_BSRA_TYPEA6:
        case MICROBLAZE_IT_BSRL_TYPEA6:
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            info->rB = VECINDEX(instruction,15,11,0); // 15:11
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            break;

        case MICROBLAZE_IT_CMP_TYPEA7:
        case MICROBLAZE_IT_CMPU_TYPEA7:
        case MICROBLAZE_IT_IDIV_TYPEA7:
        case MICROBLAZE_IT_IDIVU_TYPEA7:
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            info->rB = VECINDEX(instruction,15,11,0); // 15:11
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            break;

        case MICROBLAZE_IT_LBU_TYPEA8:
        case MICROBLAZE_IT_LBUR_TYPEA8:
        case MICROBLAZE_IT_LHU_TYPEA8:
        case MICROBLAZE_IT_LHUR_TYPEA8:
        case MICROBLAZE_IT_LW_TYPEA8:
        case MICROBLAZE_IT_LWR_TYPEA8:
        case MICROBLAZE_IT_SB_TYPEA8:
        case MICROBLAZE_IT_SBR_TYPEA8:
        case MICROBLAZE_IT_SH_TYPEA8:
        case MICROBLAZE_IT_SHR_TYPEA8:
        case MICROBLAZE_IT_SW_TYPEA8:
        case MICROBLAZE_IT_SWR_TYPEA8:
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            info->rB = VECINDEX(instruction,15,11,0); // 15:11
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            break;

        case MICROBLAZE_IT_MFS_TYPEA9:
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            info->rS = VECINDEX(instruction,13,0,0); // 13:0
            break;

        case MICROBLAZE_IT_MTS_TYPEAA:
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            info->rS = VECINDEX(instruction,13,0,0); // 13:0
            break;

        case MICROBLAZE_IT_CLZ_TYPEAB:
        case MICROBLAZE_IT_FINT_TYPEAB:
        case MICROBLAZE_IT_FLT_TYPEAB:
        case MICROBLAZE_IT_FSQRT_TYPEAB:
        case MICROBLAZE_IT_SEXT16_TYPEAB:
        case MICROBLAZE_IT_SEXT8_TYPEAB:
        case MICROBLAZE_IT_SRA_TYPEAB:
        case MICROBLAZE_IT_SRC_TYPEAB:
        case MICROBLAZE_IT_SRL_TYPEAB:
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            break;

        case MICROBLAZE_IT_WDC_TYPEAC:
        case MICROBLAZE_IT_WDCCLR_TYPEAC:
        case MICROBLAZE_IT_WDCFL_TYPEAC:
        case MICROBLAZE_IT_WIC_TYPEAC:
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            info->rB = VECINDEX(instruction,15,11,0); // 15:11
            break;

        case MICROBLAZE_IT_ADDI_TYPEB1:
        case MICROBLAZE_IT_ADDIC_TYPEB1:
        case MICROBLAZE_IT_ADDIK_TYPEB1:
        case MICROBLAZE_IT_ADDIKC_TYPEB1:
        case MICROBLAZE_IT_ANDI_TYPEB1:
        case MICROBLAZE_IT_ANDNI_TYPEB1:
        case MICROBLAZE_IT_LBUI_TYPEB1:
        case MICROBLAZE_IT_LHUI_TYPEB1:
        case MICROBLAZE_IT_LWI_TYPEB1:
        case MICROBLAZE_IT_MULI_TYPEB1:
        case MICROBLAZE_IT_ORI_TYPEB1:
        case MICROBLAZE_IT_RSUBI_TYPEB1:
        case MICROBLAZE_IT_RSUBIC_TYPEB1:
        case MICROBLAZE_IT_RSUBIK_TYPEB1:
        case MICROBLAZE_IT_RSUBIKC_TYPEB1:
        case MICROBLAZE_IT_SBI_TYPEB1:
        case MICROBLAZE_IT_SHI_TYPEB1:
        case MICROBLAZE_IT_SWI_TYPEB1:
        case MICROBLAZE_IT_XORI_TYPEB1:
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            info->simm = VECINDEX(instruction,15,0,0); // 15:0
            info->simm = SEXTEND(info->simm,15);
            break;

        case MICROBLAZE_IT_BEQI_TYPEB2:
        case MICROBLAZE_IT_BEQID_TYPEB2:
        case MICROBLAZE_IT_BGEI_TYPEB2:
        case MICROBLAZE_IT_BGEID_TYPEB2:
        case MICROBLAZE_IT_BGTI_TYPEB2:
        case MICROBLAZE_IT_BGTID_TYPEB2:
        case MICROBLAZE_IT_BLEI_TYPEB2:
        case MICROBLAZE_IT_BLEID_TYPEB2:
        case MICROBLAZE_IT_BLTI_TYPEB2:
        case MICROBLAZE_IT_BLTID_TYPEB2:
        case MICROBLAZE_IT_BNEI_TYPEB2:
        case MICROBLAZE_IT_BNEID_TYPEB2:
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            info->simm = VECINDEX(instruction,15,0,0); // 15:0
            info->simm = SEXTEND(info->simm,15);
            break;

        case MICROBLAZE_IT_BRAI_TYPEB3:
        case MICROBLAZE_IT_BRAID_TYPEB3:
        case MICROBLAZE_IT_BRI_TYPEB3:
        case MICROBLAZE_IT_BRID_TYPEB3:
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            info->simm = VECINDEX(instruction,15,0,0); // 15:0
            info->simm = SEXTEND(info->simm,15);
            break;

        case MICROBLAZE_IT_BRALID_TYPEB4:
        case MICROBLAZE_IT_BRLID_TYPEB4:
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            info->simm = VECINDEX(instruction,15,0,0); // 15:0
            info->simm = SEXTEND(info->simm,15);
            break;

        case MICROBLAZE_IT_BRKI_TYPEB5:
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            info->simm = VECINDEX(instruction,15,0,0); // 15:0
            info->simm = SEXTEND(info->simm,15);
            break;

        case MICROBLAZE_IT_BSLLI_TYPEB6:
        case MICROBLAZE_IT_BSRAI_TYPEB6:
        case MICROBLAZE_IT_BSRLI_TYPEB6:
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            info->uimm = VECINDEX(instruction,4,0,0); // 4:0
            break;

        case MICROBLAZE_IT_MBAR_TYPEB8:
            info->simm = VECINDEX(instruction,25,21,0); // 25:21
            info->simm = SEXTEND(info->simm,4);
            break;

        case MICROBLAZE_IT_MSRCLR_TYPEB9:
        case MICROBLAZE_IT_MSRSET_TYPEB9:
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            info->uimm = VECINDEX(instruction,14,0,0); // 14:0
            break;

        case MICROBLAZE_IT_RTBD_TYPEBA:
        case MICROBLAZE_IT_RTED_TYPEBA:
        case MICROBLAZE_IT_RTID_TYPEBA:
        case MICROBLAZE_IT_RTSD_TYPEBA:
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            info->simm = VECINDEX(instruction,15,0,0); // 15:0
            info->simm = SEXTEND(info->simm,15);
            break;

        case MICROBLAZE_IT_AGET_TYPEC1:
        case MICROBLAZE_IT_CAGET_TYPEC1:
        case MICROBLAZE_IT_CGET_TYPEC1:
        case MICROBLAZE_IT_EAGET_TYPEC1:
        case MICROBLAZE_IT_ECAGET_TYPEC1:
        case MICROBLAZE_IT_ECGET_TYPEC1:
        case MICROBLAZE_IT_EGET_TYPEC1:
        case MICROBLAZE_IT_GET_TYPEC1:
        case MICROBLAZE_IT_NAGET_TYPEC1:
        case MICROBLAZE_IT_NCAGET_TYPEC1:
        case MICROBLAZE_IT_NCGET_TYPEC1:
        case MICROBLAZE_IT_NEAGET_TYPEC1:
        case MICROBLAZE_IT_NECAGET_TYPEC1:
        case MICROBLAZE_IT_NECGET_TYPEC1:
        case MICROBLAZE_IT_NEGET_TYPEC1:
        case MICROBLAZE_IT_NGET_TYPEC1:
        case MICROBLAZE_IT_TAGET_TYPEC1:
        case MICROBLAZE_IT_TCAGET_TYPEC1:
        case MICROBLAZE_IT_TCGET_TYPEC1:
        case MICROBLAZE_IT_TEAGET_TYPEC1:
        case MICROBLAZE_IT_TECAGET_TYPEC1:
        case MICROBLAZE_IT_TECGET_TYPEC1:
        case MICROBLAZE_IT_TEGET_TYPEC1:
        case MICROBLAZE_IT_TGET_TYPEC1:
        case MICROBLAZE_IT_TNAGET_TYPEC1:
        case MICROBLAZE_IT_TNCAGET_TYPEC1:
        case MICROBLAZE_IT_TNCGET_TYPEC1:
        case MICROBLAZE_IT_TNEAGET_TYPEC1:
        case MICROBLAZE_IT_TNECAGET_TYPEC1:
        case MICROBLAZE_IT_TNECGET_TYPEC1:
        case MICROBLAZE_IT_TNEGET_TYPEC1:
        case MICROBLAZE_IT_TNGET_TYPEC1:
            info->FSLx = VECINDEX(instruction,3,0,0); // 3:0
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            break;

        case MICROBLAZE_IT_AGETD_TYPEC2:
        case MICROBLAZE_IT_CAGETD_TYPEC2:
        case MICROBLAZE_IT_CGETD_TYPEC2:
        case MICROBLAZE_IT_EAGETD_TYPEC2:
        case MICROBLAZE_IT_ECAGETD_TYPEC2:
        case MICROBLAZE_IT_ECGETD_TYPEC2:
        case MICROBLAZE_IT_EGETD_TYPEC2:
        case MICROBLAZE_IT_GETD_TYPEC2:
        case MICROBLAZE_IT_NAGETD_TYPEC2:
        case MICROBLAZE_IT_NCAGETD_TYPEC2:
        case MICROBLAZE_IT_NCGETD_TYPEC2:
        case MICROBLAZE_IT_NEAGETD_TYPEC2:
        case MICROBLAZE_IT_NECAGETD_TYPEC2:
        case MICROBLAZE_IT_NECGETD_TYPEC2:
        case MICROBLAZE_IT_NEGETD_TYPEC2:
        case MICROBLAZE_IT_NGETD_TYPEC2:
        case MICROBLAZE_IT_TAGETD_TYPEC2:
        case MICROBLAZE_IT_TCAGETD_TYPEC2:
        case MICROBLAZE_IT_TCGETD_TYPEC2:
        case MICROBLAZE_IT_TEAGETD_TYPEC2:
        case MICROBLAZE_IT_TECAGETD_TYPEC2:
        case MICROBLAZE_IT_TECGETD_TYPEC2:
        case MICROBLAZE_IT_TEGETD_TYPEC2:
        case MICROBLAZE_IT_TGETD_TYPEC2:
        case MICROBLAZE_IT_TNAGETD_TYPEC2:
        case MICROBLAZE_IT_TNCAGETD_TYPEC2:
        case MICROBLAZE_IT_TNCGETD_TYPEC2:
        case MICROBLAZE_IT_TNEAGETD_TYPEC2:
        case MICROBLAZE_IT_TNECAGETD_TYPEC2:
        case MICROBLAZE_IT_TNECGETD_TYPEC2:
        case MICROBLAZE_IT_TNEGETD_TYPEC2:
        case MICROBLAZE_IT_TNGETD_TYPEC2:
            info->rB = VECINDEX(instruction,15,11,0); // 15:11
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            break;

        case MICROBLAZE_IT_APUT_TYPEC3:
        case MICROBLAZE_IT_CAPUT_TYPEC3:
        case MICROBLAZE_IT_CPUT_TYPEC3:
        case MICROBLAZE_IT_NAPUT_TYPEC3:
        case MICROBLAZE_IT_NCAPUT_TYPEC3:
        case MICROBLAZE_IT_NCPUT_TYPEC3:
        case MICROBLAZE_IT_NPUT_TYPEC3:
        case MICROBLAZE_IT_PUT_TYPEC3:
            info->FSLx = VECINDEX(instruction,3,0,0); // 3:0
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            break;

        case MICROBLAZE_IT_APUTD_TYPEC3D:
        case MICROBLAZE_IT_CAPUTD_TYPEC3D:
        case MICROBLAZE_IT_CPUTD_TYPEC3D:
        case MICROBLAZE_IT_NAPUTD_TYPEC3D:
        case MICROBLAZE_IT_NCAPUTD_TYPEC3D:
        case MICROBLAZE_IT_NCPUTD_TYPEC3D:
        case MICROBLAZE_IT_NPUTD_TYPEC3D:
        case MICROBLAZE_IT_PUTD_TYPEC3D:
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            info->rB = VECINDEX(instruction,15,11,0); // 15:11
            break;

        case MICROBLAZE_IT_TAPUT_TYPEC4:
        case MICROBLAZE_IT_TCAPUT_TYPEC4:
        case MICROBLAZE_IT_TCPUT_TYPEC4:
        case MICROBLAZE_IT_TNAPUT_TYPEC4:
        case MICROBLAZE_IT_TNCAPUT_TYPEC4:
        case MICROBLAZE_IT_TNCPUT_TYPEC4:
        case MICROBLAZE_IT_TNPUT_TYPEC4:
        case MICROBLAZE_IT_TPUT_TYPEC4:
            info->FSLx = VECINDEX(instruction,3,0,0); // 3:0
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            break;

        case MICROBLAZE_IT_TAPUTD_TYPEC4D:
        case MICROBLAZE_IT_TCAPUTD_TYPEC4D:
        case MICROBLAZE_IT_TCPUTD_TYPEC4D:
        case MICROBLAZE_IT_TNAPUTD_TYPEC4D:
        case MICROBLAZE_IT_TNCAPUTD_TYPEC4D:
        case MICROBLAZE_IT_TNCPUTD_TYPEC4D:
        case MICROBLAZE_IT_TNPUTD_TYPEC4D:
        case MICROBLAZE_IT_TPUTD_TYPEC4D:
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            info->rB = VECINDEX(instruction,15,11,0); // 15:11
            break;

        case MICROBLAZE_IT_IMM_TYPEI1:
            info->simmhi = VECINDEX(instruction,15,0,0); // 15:0
            info->simmhi = SHIFTL(info->simmhi,16);
            info->simmhi = SEXTEND(info->simmhi,31);
            break;

        case MICROBLAZE_IT_NOP_TYPEX:
            break;

        case MICROBLAZE_IT_INSTR32:
        case MICROBLAZE_IT_LAST:
            // Default to get the indices
            info->rA = VECINDEX(instruction,20,16,0); // 20:16
            info->rB = VECINDEX(instruction,15,11,0); // 15:11
            info->rD = VECINDEX(instruction,25,21,0); // 25:21
            info->simm = VECINDEX(instruction,15,0,0); // 15:0
            info->simm = SEXTEND(info->simm,15);
            break;
    }
    return;
}
Esempio n. 2
0
int print_disassembly(FILE *out, struct instruction *i, int flags)
{
    if (flags & ASM_AS_DATA)
        return fprintf(out, ".word 0x%08x", i->u.word);

    if (flags & ASM_AS_CHAR) {
        char buf[10];
        if (is_printable(i->u.word, sizeof buf, buf))
            return fprintf(out, ".word '%s'%*s", buf, (int)(2 - strlen(buf)), "");
        else
            return fprintf(out, "          ");
    }

    int type = i->u._xxxx.t;
    switch (type) {
        default:
            if (i->u.word == 0xffffffff)
                return fprintf(out, "illegal");
            else
                return fprintf(out, ".word 0x%08x", i->u.word);

        case 0x0:
        case 0x1:
        case 0x2:
        case 0x3:
        case 0x4:
        case 0x5:
        case 0x6:
        case 0x7:
            break;
    }

    struct instruction_general *g = &i->u._0xxx;

    if (!op_meta[g->op].valid)   // reserved
        return fprintf(out, ".word 0x%08x", i->u.word);

    int rd = g->dd &  1;
    int ld = g->dd == 2;

    // LHS
          char    f0 = ld ? '[' : ' ';        // left side dereferenced ?
          char    f1 = 'A' + g->z;            // register name for Z
          char    f2 = ld ? ']' : ' ';        // left side dereferenced ?

    // arrow
    const char   *f3 = (g->dd == 3) ? "->" : "<-";    // arrow direction

    // RHS
          char    f4 = rd ? '[' : ' ';        // right side dereferenced ?
          char    f5 = 'A' + g->x;            // register name for X
    const char   *f6 = op_meta[g->op].name;   // operator name
          char    f7 = 'A' + g->y;            // register name for Y
          int32_t f8 = SEXTEND(12,g->imm);    // immediate value, sign-extended
          char    f9 = rd ? ']' : ' ';        // right side dereferenced ?

    int hex   = op_meta[g->op].hex;
    int inert = op_meta[g->op].inert;
    int opXA  = g->x == 0;
    int opYA  = g->y == 0;
    int op3   = g->p ? !opYA : (!!g->imm);
    int op2   = !inert || (g->p ? (g->imm || opYA) : !opYA);
    int op1   = !(opXA && inert) || (!op2 && !op3);
    int kind  = !!g->p;

    if (flags & ASM_VERBOSE)
        op1 = op2 = op3 = hex = 1;

    if (!(flags & (ASM_NO_SUGAR | ASM_VERBOSE))) {
        if (g->op == OP_BITWISE_XORN && g->y == 0) {
            f7 = f5;    // Y slot is now X
            f5 = ' ';   // don't print X
            f6 = "~";   // change op to a unary not
        } else if (g->op == OP_SUBTRACT && g->x == 0) {
            f5 = ' ';   // don't print X
        }
    }

    #define C_(E,D,C,B,A) (((E) << 4) | ((D) << 3) | ((C) << 2) | ((B) << 1) | (A))
    // We'd like to use positional references in these format strings, but to
    // preserve compatibility with Win32 libc, we don't.
    // indices : hex, g->p, op1, op2, op3
    static const char *fmts[C_(1,1,1,1,1)+1] = {
      //[C_(0,0,0,0,0)] = "%c%c%c %s %c"                   "%c", // [Z] <- [           ]
        [C_(0,0,0,0,1)] = "%c%c%c %s %c"              "%-10d%c", // [Z] <- [         -0]
        [C_(0,0,0,1,0)] = "%c%c%c %s %c"         "%c"      "%c", // [Z] <- [    Y      ]
        [C_(0,0,0,1,1)] = "%c%c%c %s %c"         "%c + %-10d%c", // [Z] <- [    Y +  -0]
        [C_(0,0,1,0,0)] = "%c%c%c %s %c%c"                 "%c", // [Z] <- [X          ]
        [C_(0,0,1,0,1)] = "%c%c%c %s %c%c"         " + %-10d%c", // [Z] <- [X     +  -0]
        [C_(0,0,1,1,0)] = "%c%c%c %s %c%c %-2s " "%c"      "%c", // [Z] <- [X - Y      ]
        [C_(0,0,1,1,1)] = "%c%c%c %s %c%c %-2s " "%c + %-10d%c", // [Z] <- [X - Y +  -0]
      //[C_(0,1,0,0,0)] = "%c%c%c %s %c"                   "%c", // [Z] <- [           ]
        [C_(0,1,0,0,1)] = "%c%c%c %s %c"                 "%c%c", // [Z] <- [          Y]
        [C_(0,1,0,1,0)] = "%c%c%c %s %c"        " %-10d"   "%c", // [Z] <- [     -0    ]
        [C_(0,1,0,1,1)] = "%c%c%c %s %c"        " %-10d + %c%c", // [Z] <- [     -0 + Y]
        [C_(0,1,1,0,0)] = "%c%c%c %s %c%c"                 "%c", // [Z] <- [X          ]
        [C_(0,1,1,0,1)] = "%c%c%c %s %c%c"            " + %c%c", // [Z] <- [X       + Y]
        [C_(0,1,1,1,0)] = "%c%c%c %s %c%c %-2s " "%-10d"   "%c", // [Z] <- [X -  -0    ]
        [C_(0,1,1,1,1)] = "%c%c%c %s %c%c %-2s " "%-10d + %c%c", // [Z] <- [X -  -0 + Y]
      //[C_(1,0,0,0,0)] = "%c%c%c %s %c"                   "%c", // [Z] <- [           ]
        [C_(1,0,0,0,1)] = "%c%c%c %s %c"             "0x%08x%c", // [Z] <- [        0x0]
        [C_(1,0,0,1,0)] = "%c%c%c %s %c"        "%c"       "%c", // [Z] <- [    Y      ]
        [C_(1,0,0,1,1)] = "%c%c%c %s %c"        "%c + 0x%08x%c", // [Z] <- [    Y + 0x0]
        [C_(1,0,1,0,0)] = "%c%c%c %s %c%c"                 "%c", // [Z] <- [X          ]
        [C_(1,0,1,0,1)] = "%c%c%c %s %c%c"        " + 0x%08x%c", // [Z] <- [X     + 0x0]
        [C_(1,0,1,1,0)] = "%c%c%c %s %c%c %-2s ""%c"       "%c", // [Z] <- [X - Y      ]
        [C_(1,0,1,1,1)] = "%c%c%c %s %c%c %-2s ""%c + 0x%08x%c", // [Z] <- [X - Y + 0x0]
      //[C_(1,1,0,0,0)] = "%c%c%c %s %c"                   "%c", // [Z] <- [           ]
        [C_(1,1,0,0,1)] = "%c%c%c %s %c"                 "%c%c", // [Z] <- [          Y]
        [C_(1,1,0,1,0)] = "%c%c%c %s %c"        "0x%08x"   "%c", // [Z] <- [    0x0    ]
        [C_(1,1,0,1,1)] = "%c%c%c %s %c"        "0x%08x + %c%c", // [Z] <- [    0x0 + Y]
        [C_(1,1,1,0,0)] = "%c%c%c %s %c%c"                 "%c", // [Z] <- [X          ]
        [C_(1,1,1,0,1)] = "%c%c%c %s %c%c"            " + %c%c", // [Z] <- [X       + Y]
        [C_(1,1,1,1,0)] = "%c%c%c %s %c%c %-2s ""0x%08x"   "%c", // [Z] <- [X - 0x0    ]
        [C_(1,1,1,1,1)] = "%c%c%c %s %c%c %-2s ""0x%08x + %c%c", // [Z] <- [X - 0x0 + Y]
    };

    #define PUT(...) return fprintf(out, fmts[C_(hex,kind,op1,op2,op3)], __VA_ARGS__)
    switch (C_(0,kind,op1,op2,op3)) {
      //case C_(0,0,0,0,0): PUT(f0,f1,f2,f3,f4,            f9); break;
        case C_(0,0,0,0,1): PUT(f0,f1,f2,f3,f4,         f8,f9); break;
        case C_(0,0,0,1,0): PUT(f0,f1,f2,f3,f4,      f7,   f9); break;
        case C_(0,0,0,1,1): PUT(f0,f1,f2,f3,f4,      f7,f8,f9); break;
        case C_(0,0,1,0,0): PUT(f0,f1,f2,f3,f4,f5,         f9); break;
        case C_(0,0,1,0,1): PUT(f0,f1,f2,f3,f4,f5,      f8,f9); break;
        case C_(0,0,1,1,0): PUT(f0,f1,f2,f3,f4,f5,f6,f7,   f9); break;
        case C_(0,0,1,1,1): PUT(f0,f1,f2,f3,f4,f5,f6,f7,f8,f9); break;
      //case C_(0,1,0,0,0): PUT(f0,f1,f2,f3,f4,            f9); break;
        case C_(0,1,0,0,1): PUT(f0,f1,f2,f3,f4,         f7,f9); break;
        case C_(0,1,0,1,0): PUT(f0,f1,f2,f3,f4,      f8,   f9); break;
        case C_(0,1,0,1,1): PUT(f0,f1,f2,f3,f4,      f8,f7,f9); break;
        case C_(0,1,1,0,0): PUT(f0,f1,f2,f3,f4,f5,         f9); break;
        case C_(0,1,1,0,1): PUT(f0,f1,f2,f3,f4,f5,      f7,f9); break;
        case C_(0,1,1,1,0): PUT(f0,f1,f2,f3,f4,f5,f6,f8,   f9); break;
        case C_(0,1,1,1,1): PUT(f0,f1,f2,f3,f4,f5,f6,f8,f7,f9); break;

        default:
            fatal(0, "Unsupported hex,kind,op1,op2,op3 %d,%d,%d,%d,%d",
                    hex,g->p,op1,op2,op3);
    }
}