Unified · Split
| @@ -1002,21 +1002,24 @@ again: · 1001 unmodified lines | ||
| 1002 | 1002 | modrm_index = -1; |
| 1003 | 1003 | modreg_index = -1; |
| 1004 | 1004 | if (pa->instr_type & OPC_MODRM) { |
| 1005 | −#ifdef TCC_TARGET_X86_64 | |
| 1006 | 1005 | if (!nb_ops) { |
| 1007 | 1006 | /* A modrm opcode without operands is a special case (e.g. mfence). |
| 1008 | 1007 | It has a group and acts as if there's an register operand 0 */ |
| 1009 | 1008 | i = 0; |
| 1010 | 1009 | ops[i].type = OP_REG; |
| 1010 | +#ifdef TCC_TARGET_X86_64 | |
| 1011 | 1011 | if (pa->sym == TOK_ASM_endbr64) |
| 1012 | 1012 | ops[i].reg = 2; // dx |
| 1013 | 1013 | else if (pa->sym >= TOK_ASM_lfence && pa->sym <= TOK_ASM_sfence) |
| 1014 | 1014 | ops[i].reg = 0; // ax |
| 1015 | +#else | |
| 1016 | + if (pa->sym == TOK_ASM_endbr32) | |
| 1017 | + ops[i].reg = 3; // bx | |
| 1018 | +#endif | |
| 1015 | 1019 | else |
| 1016 | 1020 | tcc_error("bad MODR/M opcode without operands"); |
| 1017 | 1021 | goto modrm_found; |
| 1018 | 1022 | } |
| 1019 | −#endif | |
| 1020 | 1023 | /* first look for an ea operand */ |
| 1021 | 1024 | for(i = 0;i < nb_ops; i++) { |
| 1022 | 1025 | if (op_type[i] & OP_EA) |
| @@ -37,7 +37,10 @@ · 36 unmodified lines | ||
| 37 | 37 | DEF_ASM_OP0(pause, 0xf390) |
| 38 | 38 | DEF_ASM_OP0(xlat, 0xd7) |
| 39 | 39 | |
| 40 | − /* strings */ | |
| 40 | + /* Control-Flow Enforcement */ | |
| 41 | + DEF_ASM_OP0L(endbr32, 0xf30f1e, 7, OPC_MODRM) | |
| 42 | + | |
| 43 | + /* strings */ | |
| 41 | 44 | ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWLX)) |
| 42 | 45 | ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWLX)) |
| 43 | 46 | |