| 4035 | //========================================================================== |
| 4036 | |
| 4037 | ExpEmit FxCompareRel::EmitCommon(VMFunctionBuilder *build, bool forcompare, bool invert) |
| 4038 | { |
| 4039 | ExpEmit op1 = left->Emit(build); |
| 4040 | ExpEmit op2 = right->Emit(build); |
| 4041 | assert(op1.RegType == op2.RegType); |
| 4042 | assert(!op1.Konst || !op2.Konst); |
| 4043 | |
| 4044 | if (op1.RegType == REGT_STRING) |
| 4045 | { |
| 4046 | ExpEmit to(build, REGT_INT); |
| 4047 | int a = Operator == '<' ? CMP_LT : |
| 4048 | Operator == '>' ? CMP_LE | CMP_CHECK : |
| 4049 | Operator == TK_Geq ? CMP_LT | CMP_CHECK : CMP_LE; |
| 4050 | |
| 4051 | if (op1.Konst) |
| 4052 | { |
| 4053 | a |= CMP_BK; |
| 4054 | } |
| 4055 | else |
| 4056 | { |
| 4057 | op1.Free(build); |
| 4058 | } |
| 4059 | if (op2.Konst) |
| 4060 | { |
| 4061 | a |= CMP_CK; |
| 4062 | } |
| 4063 | else |
| 4064 | { |
| 4065 | op2.Free(build); |
| 4066 | } |
| 4067 | if (invert) a ^= CMP_CHECK; |
| 4068 | |
| 4069 | if (!forcompare) build->Emit(OP_LI, to.RegNum, 0, 0); |
| 4070 | build->Emit(OP_CMPS, a, op1.RegNum, op2.RegNum); |
| 4071 | if (!forcompare) |
| 4072 | { |
| 4073 | build->Emit(OP_JMP, 1); |
| 4074 | build->Emit(OP_LI, to.RegNum, 1); |
| 4075 | } |
| 4076 | return to; |
| 4077 | } |
| 4078 | else |
| 4079 | { |
| 4080 | assert(op1.RegType == REGT_INT || op1.RegType == REGT_FLOAT); |
| 4081 | assert(Operator == '<' || Operator == '>' || Operator == TK_Geq || Operator == TK_Leq); |
| 4082 | static const VM_UBYTE InstrMap[][4] = |
| 4083 | { |
| 4084 | { OP_LT_RR, OP_LTF_RR, OP_LTU_RR, 0 }, // < |
| 4085 | { OP_LE_RR, OP_LEF_RR, OP_LEU_RR, 1 }, // > |
| 4086 | { OP_LT_RR, OP_LTF_RR, OP_LTU_RR, 1 }, // >= |
| 4087 | { OP_LE_RR, OP_LEF_RR, OP_LEU_RR, 0 } // <= |
| 4088 | }; |
| 4089 | int instr, check; |
| 4090 | ExpEmit to(build, REGT_INT); |
| 4091 | int index = Operator == '<' ? 0 : |
| 4092 | Operator == '>' ? 1 : |
| 4093 | Operator == TK_Geq ? 2 : 3; |
| 4094 | |