- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
#define OPCODEFORMAT_CASE(opcode, format) case opcode: return format; break
inline OpcodeFormat getOpcodeFormat(Opcode opcode)
{
switch (opcode)
{
OPCODEFORMAT_CASE(NOP , OPCODE);
OPCODEFORMAT_CASE(MOV_RR , OPCODE_RR);
OPCODEFORMAT_CASE(MOV_RC , OPCODE_RC);
OPCODEFORMAT_CASE(MOV_RM , OPCODE_RM);
OPCODEFORMAT_CASE(MOV_MR , OPCODE_MR);
OPCODEFORMAT_CASE(MOV_MC , OPCODE_MC);
OPCODEFORMAT_CASE(MOV_MM , OPCODE_MM);
OPCODEFORMAT_CASE(ADD , OPCODE_RR);
OPCODEFORMAT_CASE(SUB , OPCODE_RR);
OPCODEFORMAT_CASE(ADD_C , OPCODE_RC);
OPCODEFORMAT_CASE(SUB_C , OPCODE_RC);
OPCODEFORMAT_CASE(MUL , OPCODE_RR);
OPCODEFORMAT_CASE(DIV , OPCODE_RR);
OPCODEFORMAT_CASE(MUL_C , OPCODE_RC);
OPCODEFORMAT_CASE(DIV_C , OPCODE_RC);
OPCODEFORMAT_CASE(LEA , OPCODE_RM);
OPCODEFORMAT_CASE(INC , OPCODE_R);
OPCODEFORMAT_CASE(DEC , OPCODE_R);
OPCODEFORMAT_CASE(INT , OPCODE_C8);
OPCODEFORMAT_CASE(CMP_RC , OPCODE_RC);
OPCODEFORMAT_CASE(JMP , OPCODE_C);
OPCODEFORMAT_CASE(JZ , OPCODE_C);
OPCODEFORMAT_CASE(JNZ , OPCODE_C);
OPCODEFORMAT_CASE(JG , OPCODE_C);
OPCODEFORMAT_CASE(JNG , OPCODE_C);
OPCODEFORMAT_CASE(JGZ , OPCODE_C);
OPCODEFORMAT_CASE(JL , OPCODE_C);
OPCODEFORMAT_CASE(CALL , OPCODE_C);
OPCODEFORMAT_CASE(PUSH_R , OPCODE_R);
OPCODEFORMAT_CASE(PUSH_C , OPCODE_C);
OPCODEFORMAT_CASE(PUSH_C8 , OPCODE_C8);
OPCODEFORMAT_CASE(POP_R , OPCODE_R);
OPCODEFORMAT_CASE(POP , OPCODE);
OPCODEFORMAT_CASE(POP8 , OPCODE);
OPCODEFORMAT_CASE(POP_M8 , OPCODE_M);
OPCODEFORMAT_CASE(POP_M16 , OPCODE_M);
OPCODEFORMAT_CASE(OUT_M8 , OPCODE_MC);
OPCODEFORMAT_CASE(OUT_M16 , OPCODE_MC);
OPCODEFORMAT_CASE(OUT_C8 , OPCODE_CC8);
OPCODEFORMAT_CASE(OUT_C16 , OPCODE_CC);
OPCODEFORMAT_CASE(OUT_R , OPCODE_RC);
OPCODEFORMAT_CASE(IN_R , OPCODE_RC);
OPCODEFORMAT_CASE(IN_M8 , OPCODE_MC);
OPCODEFORMAT_CASE(IN_M16 , OPCODE_MC);
OPCODEFORMAT_CASE(RET , OPCODE);
default: return (OpcodeFormat)0xFF; break;
}
}
#undef OPCODEFORMAT_CASE
Так то да, гцц насколько помню три варианта умеет для свича -- двоичный поиск (если мало и неплотно), одноуровневый массив (много и плотно) и двухуровневый массив (не очень плотно и повторяются).
Шок! Вореции спасают от заражения омикроном.
Кто же подаст тебе чашку воды, запить эвтаназионный препарат, перед смертью?
Какой UB )))
Кобенации флажков в духе Value1 | Value2, насколько я понимаю, не противоречат стандарту. А вот что-то более длинное -- хрен бы знал, там очень сложная формулировка про underlying type и я её до конца не понимаю.
Чисто технически enum вряд-ли занимает меньше байта, так что ничего убийственного не должно случиться (хотя если это реально UB, то компилятор просто выкинет всё нахуй, и дело с концом)
Всё не выкинет, но у меня сомнения насчёт switch. К примеру, вдруг конпелятор посчитает, что раз у енума всего 2 варианта и underlying type явно не указан, то можно проверять их как "0 и не 0"? И 0xFF уйдёт в ветку с "не 0".
9.7.1 Enumeration declarations
8. For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the underlying type. Otherwise, the values of the enumeration are the values representable by a hypothetical integer type with minimal width M such that all enumerators can be represented.
default: return (OpcodeFormat)0xFF; break;
и будет там мусор в возвращаемом значении
Так как ты определил тип OpcodeFormat?
> hypothetical
integer type with minimal width M such that all enumerators can be represented.
Ну то есть там омжет быть signed char, например? И вот, 0xFF будет какашкаокок
С другой стороны, если мы явно указали underlying type и 0xFF в него помещается, то вроде всё норм.
10. <...> If the enumeration type does not have a fixed underlying type, the value is unchanged if the original value is within the range of the enumeration values (9.7.1), and otherwise, the behavior is undefined. <...>
Вооюще в идеальном мире ты никогда не должен представлять енумы в виде цифр, разве что ради сериализации какой
> не должен представлять енумы в виде цифр
Ну почему, если явно указать underlying type для енума, то всё будет норм. Главное за его пределы не вылетать.
Да и с неявным типом более-менее работают битовые маски если что попало не пихать.
Ты из файла прочитал 0x80, но такой маски в енуме ещё не было. Но т.к. ты указал тип явно (например uint8_t), то всё будет норм, просто незнакомый флаг не обработается. UB'а не будет.