@@ -990,8 +990,12 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
990
990
goto jeq_common ;
991
991
case BPF_JMP | BPF_JEQ | BPF_X : /* JMP_REG */
992
992
case BPF_JMP | BPF_JNE | BPF_X :
993
+ case BPF_JMP | BPF_JSLT | BPF_X :
994
+ case BPF_JMP | BPF_JSLE | BPF_X :
993
995
case BPF_JMP | BPF_JSGT | BPF_X :
994
996
case BPF_JMP | BPF_JSGE | BPF_X :
997
+ case BPF_JMP | BPF_JLT | BPF_X :
998
+ case BPF_JMP | BPF_JLE | BPF_X :
995
999
case BPF_JMP | BPF_JGT | BPF_X :
996
1000
case BPF_JMP | BPF_JGE | BPF_X :
997
1001
case BPF_JMP | BPF_JSET | BPF_X :
@@ -1013,41 +1017,47 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
1013
1017
cmp_eq = false;
1014
1018
dst = MIPS_R_AT ;
1015
1019
src = MIPS_R_ZERO ;
1016
- } else if (BPF_OP (insn -> code ) == BPF_JSGT ) {
1020
+ } else if (BPF_OP (insn -> code ) == BPF_JSGT || BPF_OP ( insn -> code ) == BPF_JSLE ) {
1017
1021
emit_instr (ctx , dsubu , MIPS_R_AT , dst , src );
1018
1022
if ((insn + 1 )-> code == (BPF_JMP | BPF_EXIT ) && insn -> off == 1 ) {
1019
1023
b_off = b_imm (exit_idx , ctx );
1020
1024
if (is_bad_offset (b_off ))
1021
1025
return - E2BIG ;
1022
- emit_instr (ctx , blez , MIPS_R_AT , b_off );
1026
+ if (BPF_OP (insn -> code ) == BPF_JSGT )
1027
+ emit_instr (ctx , blez , MIPS_R_AT , b_off );
1028
+ else
1029
+ emit_instr (ctx , bgtz , MIPS_R_AT , b_off );
1023
1030
emit_instr (ctx , nop );
1024
1031
return 2 ; /* We consumed the exit. */
1025
1032
}
1026
1033
b_off = b_imm (this_idx + insn -> off + 1 , ctx );
1027
1034
if (is_bad_offset (b_off ))
1028
1035
return - E2BIG ;
1029
- emit_instr (ctx , bgtz , MIPS_R_AT , b_off );
1036
+ if (BPF_OP (insn -> code ) == BPF_JSGT )
1037
+ emit_instr (ctx , bgtz , MIPS_R_AT , b_off );
1038
+ else
1039
+ emit_instr (ctx , blez , MIPS_R_AT , b_off );
1030
1040
emit_instr (ctx , nop );
1031
1041
break ;
1032
- } else if (BPF_OP (insn -> code ) == BPF_JSGE ) {
1042
+ } else if (BPF_OP (insn -> code ) == BPF_JSGE || BPF_OP ( insn -> code ) == BPF_JSLT ) {
1033
1043
emit_instr (ctx , slt , MIPS_R_AT , dst , src );
1034
- cmp_eq = true ;
1044
+ cmp_eq = BPF_OP ( insn -> code ) == BPF_JSGE ;
1035
1045
dst = MIPS_R_AT ;
1036
1046
src = MIPS_R_ZERO ;
1037
- } else if (BPF_OP (insn -> code ) == BPF_JGT ) {
1047
+ } else if (BPF_OP (insn -> code ) == BPF_JGT || BPF_OP ( insn -> code ) == BPF_JLE ) {
1038
1048
/* dst or src could be AT */
1039
1049
emit_instr (ctx , dsubu , MIPS_R_T8 , dst , src );
1040
1050
emit_instr (ctx , sltu , MIPS_R_AT , dst , src );
1041
1051
/* SP known to be non-zero, movz becomes boolean not */
1042
1052
emit_instr (ctx , movz , MIPS_R_T9 , MIPS_R_SP , MIPS_R_T8 );
1043
1053
emit_instr (ctx , movn , MIPS_R_T9 , MIPS_R_ZERO , MIPS_R_T8 );
1044
1054
emit_instr (ctx , or , MIPS_R_AT , MIPS_R_T9 , MIPS_R_AT );
1045
- cmp_eq = true ;
1055
+ cmp_eq = BPF_OP ( insn -> code ) == BPF_JGT ;
1046
1056
dst = MIPS_R_AT ;
1047
1057
src = MIPS_R_ZERO ;
1048
- } else if (BPF_OP (insn -> code ) == BPF_JGE ) {
1058
+ } else if (BPF_OP (insn -> code ) == BPF_JGE || BPF_OP ( insn -> code ) == BPF_JLT ) {
1049
1059
emit_instr (ctx , sltu , MIPS_R_AT , dst , src );
1050
- cmp_eq = true ;
1060
+ cmp_eq = BPF_OP ( insn -> code ) == BPF_JGE ;
1051
1061
dst = MIPS_R_AT ;
1052
1062
src = MIPS_R_ZERO ;
1053
1063
} else { /* JNE/JEQ case */
@@ -1110,6 +1120,8 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
1110
1120
break ;
1111
1121
case BPF_JMP | BPF_JSGT | BPF_K : /* JMP_IMM */
1112
1122
case BPF_JMP | BPF_JSGE | BPF_K : /* JMP_IMM */
1123
+ case BPF_JMP | BPF_JSLT | BPF_K : /* JMP_IMM */
1124
+ case BPF_JMP | BPF_JSLE | BPF_K : /* JMP_IMM */
1113
1125
cmp_eq = (BPF_OP (insn -> code ) == BPF_JSGE );
1114
1126
dst = ebpf_to_mips_reg (ctx , insn , dst_reg_fp_ok );
1115
1127
if (dst < 0 )
@@ -1120,65 +1132,92 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
1120
1132
b_off = b_imm (exit_idx , ctx );
1121
1133
if (is_bad_offset (b_off ))
1122
1134
return - E2BIG ;
1123
- if (cmp_eq )
1124
- emit_instr (ctx , bltz , dst , b_off );
1125
- else
1135
+ switch (BPF_OP (insn -> code )) {
1136
+ case BPF_JSGT :
1126
1137
emit_instr (ctx , blez , dst , b_off );
1138
+ break ;
1139
+ case BPF_JSGE :
1140
+ emit_instr (ctx , bltz , dst , b_off );
1141
+ break ;
1142
+ case BPF_JSLT :
1143
+ emit_instr (ctx , bgez , dst , b_off );
1144
+ break ;
1145
+ case BPF_JSLE :
1146
+ emit_instr (ctx , bgtz , dst , b_off );
1147
+ break ;
1148
+ }
1127
1149
emit_instr (ctx , nop );
1128
1150
return 2 ; /* We consumed the exit. */
1129
1151
}
1130
1152
b_off = b_imm (this_idx + insn -> off + 1 , ctx );
1131
1153
if (is_bad_offset (b_off ))
1132
1154
return - E2BIG ;
1133
- if (cmp_eq )
1134
- emit_instr (ctx , bgez , dst , b_off );
1135
- else
1155
+ switch (BPF_OP (insn -> code )) {
1156
+ case BPF_JSGT :
1136
1157
emit_instr (ctx , bgtz , dst , b_off );
1158
+ break ;
1159
+ case BPF_JSGE :
1160
+ emit_instr (ctx , bgez , dst , b_off );
1161
+ break ;
1162
+ case BPF_JSLT :
1163
+ emit_instr (ctx , bltz , dst , b_off );
1164
+ break ;
1165
+ case BPF_JSLE :
1166
+ emit_instr (ctx , blez , dst , b_off );
1167
+ break ;
1168
+ }
1137
1169
emit_instr (ctx , nop );
1138
1170
break ;
1139
1171
}
1140
1172
/*
1141
1173
* only "LT" compare available, so we must use imm + 1
1142
- * to generate "GT"
1174
+ * to generate "GT" and imm -1 to generate LE
1143
1175
*/
1144
- t64s = insn -> imm + (cmp_eq ? 0 : 1 );
1176
+ if (BPF_OP (insn -> code ) == BPF_JSGT )
1177
+ t64s = insn -> imm + 1 ;
1178
+ else if (BPF_OP (insn -> code ) == BPF_JSLE )
1179
+ t64s = insn -> imm + 1 ;
1180
+ else
1181
+ t64s = insn -> imm ;
1182
+
1183
+ cmp_eq = BPF_OP (insn -> code ) == BPF_JSGT || BPF_OP (insn -> code ) == BPF_JSGE ;
1145
1184
if (t64s >= S16_MIN && t64s <= S16_MAX ) {
1146
1185
emit_instr (ctx , slti , MIPS_R_AT , dst , (int )t64s );
1147
1186
src = MIPS_R_AT ;
1148
1187
dst = MIPS_R_ZERO ;
1149
- cmp_eq = true;
1150
1188
goto jeq_common ;
1151
1189
}
1152
1190
emit_const_to_reg (ctx , MIPS_R_AT , (u64 )t64s );
1153
1191
emit_instr (ctx , slt , MIPS_R_AT , dst , MIPS_R_AT );
1154
1192
src = MIPS_R_AT ;
1155
1193
dst = MIPS_R_ZERO ;
1156
- cmp_eq = true;
1157
1194
goto jeq_common ;
1158
1195
1159
1196
case BPF_JMP | BPF_JGT | BPF_K :
1160
1197
case BPF_JMP | BPF_JGE | BPF_K :
1198
+ case BPF_JMP | BPF_JLT | BPF_K :
1199
+ case BPF_JMP | BPF_JLE | BPF_K :
1161
1200
cmp_eq = (BPF_OP (insn -> code ) == BPF_JGE );
1162
1201
dst = ebpf_to_mips_reg (ctx , insn , dst_reg_fp_ok );
1163
1202
if (dst < 0 )
1164
1203
return dst ;
1165
1204
/*
1166
1205
* only "LT" compare available, so we must use imm + 1
1167
- * to generate "GT"
1206
+ * to generate "GT" and imm -1 to generate LE
1168
1207
*/
1169
- t64s = (u64 )(u32 )(insn -> imm ) + (cmp_eq ? 0 : 1 );
1170
- if (t64s >= 0 && t64s <= S16_MAX ) {
1171
- emit_instr (ctx , sltiu , MIPS_R_AT , dst , (int )t64s );
1172
- src = MIPS_R_AT ;
1173
- dst = MIPS_R_ZERO ;
1174
- cmp_eq = true;
1175
- goto jeq_common ;
1176
- }
1208
+ if (BPF_OP (insn -> code ) == BPF_JGT )
1209
+ t64s = (u64 )(u32 )(insn -> imm ) + 1 ;
1210
+ else if (BPF_OP (insn -> code ) == BPF_JLE )
1211
+ t64s = (u64 )(u32 )(insn -> imm ) + 1 ;
1212
+ else
1213
+ t64s = (u64 )(u32 )(insn -> imm );
1214
+
1215
+ cmp_eq = BPF_OP (insn -> code ) == BPF_JGT || BPF_OP (insn -> code ) == BPF_JGE ;
1216
+
1177
1217
emit_const_to_reg (ctx , MIPS_R_AT , (u64 )t64s );
1178
1218
emit_instr (ctx , sltu , MIPS_R_AT , dst , MIPS_R_AT );
1179
1219
src = MIPS_R_AT ;
1180
1220
dst = MIPS_R_ZERO ;
1181
- cmp_eq = true;
1182
1221
goto jeq_common ;
1183
1222
1184
1223
case BPF_JMP | BPF_JSET | BPF_K : /* JMP_IMM */
@@ -1712,10 +1751,14 @@ static int reg_val_propagate_range(struct jit_ctx *ctx, u64 initial_rvt,
1712
1751
case BPF_JEQ :
1713
1752
case BPF_JGT :
1714
1753
case BPF_JGE :
1754
+ case BPF_JLT :
1755
+ case BPF_JLE :
1715
1756
case BPF_JSET :
1716
1757
case BPF_JNE :
1717
1758
case BPF_JSGT :
1718
1759
case BPF_JSGE :
1760
+ case BPF_JSLT :
1761
+ case BPF_JSLE :
1719
1762
if (follow_taken ) {
1720
1763
rvt [idx ] |= RVT_BRANCH_TAKEN ;
1721
1764
idx += insn -> off ;
0 commit comments