@@ -171,3 +171,117 @@ fn ensure_constant_idx(c: &mut Compiler, e: &ExpDesc) -> u32 {
171171 _ => 0 ,
172172 }
173173}
174+
175+ //======================================================================================
176+ // Register-based helpers for compile_binary_expr_to
177+ //======================================================================================
178+
179+ /// Emit arithmetic operation with immediate constant (for compile_binary_expr_to)
180+ /// Returns Some(result_reg) if immediate/constant form was used, None otherwise
181+ pub fn emit_arith_imm (
182+ c : & mut Compiler ,
183+ op : BinaryOperator ,
184+ left_reg : u32 ,
185+ int_val : i64 ,
186+ result_reg : u32 ,
187+ ) -> Option < u32 > {
188+ let imm = ( ( int_val + 127 ) & 0xff ) as u32 ;
189+ let imm_mmbini = ( ( int_val + 128 ) & 0xff ) as u32 ;
190+
191+ match op {
192+ BinaryOperator :: OpAdd => {
193+ emit ( c, Instruction :: encode_abc ( OpCode :: AddI , result_reg, left_reg, imm) ) ;
194+ emit ( c, Instruction :: create_abck ( OpCode :: MmBinI , left_reg, imm_mmbini, TagMethod :: Add . as_u32 ( ) , false ) ) ;
195+ Some ( result_reg)
196+ }
197+ BinaryOperator :: OpSub => {
198+ let neg_imm = ( ( -int_val + 127 ) & 0xff ) as u32 ;
199+ emit ( c, Instruction :: encode_abc ( OpCode :: AddI , result_reg, left_reg, neg_imm) ) ;
200+ emit ( c, Instruction :: create_abck ( OpCode :: MmBinI , left_reg, imm_mmbini, TagMethod :: Sub . as_u32 ( ) , false ) ) ;
201+ Some ( result_reg)
202+ }
203+ _ => None ,
204+ }
205+ }
206+
207+ /// Emit arithmetic operation with constant from K table (for compile_binary_expr_to)
208+ pub fn emit_arith_k (
209+ c : & mut Compiler ,
210+ op : BinaryOperator ,
211+ left_reg : u32 ,
212+ const_idx : u32 ,
213+ result_reg : u32 ,
214+ ) -> Option < u32 > {
215+ let ( op_k, tm) = match op {
216+ BinaryOperator :: OpAdd => ( OpCode :: AddK , TagMethod :: Add ) ,
217+ BinaryOperator :: OpSub => ( OpCode :: SubK , TagMethod :: Sub ) ,
218+ BinaryOperator :: OpMul => ( OpCode :: MulK , TagMethod :: Mul ) ,
219+ BinaryOperator :: OpDiv => ( OpCode :: DivK , TagMethod :: Div ) ,
220+ BinaryOperator :: OpIDiv => ( OpCode :: IDivK , TagMethod :: IDiv ) ,
221+ BinaryOperator :: OpMod => ( OpCode :: ModK , TagMethod :: Mod ) ,
222+ BinaryOperator :: OpPow => ( OpCode :: PowK , TagMethod :: Pow ) ,
223+ _ => return None ,
224+ } ;
225+
226+ emit ( c, Instruction :: encode_abc ( op_k, result_reg, left_reg, const_idx) ) ;
227+ emit ( c, Instruction :: create_abck ( OpCode :: MmBinK , left_reg, const_idx, tm. as_u32 ( ) , false ) ) ;
228+ Some ( result_reg)
229+ }
230+
231+ /// Emit shift operation with immediate (for compile_binary_expr_to)
232+ pub fn emit_shift_imm (
233+ c : & mut Compiler ,
234+ op : BinaryOperator ,
235+ left_reg : u32 ,
236+ int_val : i64 ,
237+ result_reg : u32 ,
238+ ) -> Option < u32 > {
239+ let imm = ( ( int_val + 127 ) & 0xff ) as u32 ;
240+ let imm_mmbini = ( ( int_val + 128 ) & 0xff ) as u32 ;
241+
242+ match op {
243+ BinaryOperator :: OpShr => {
244+ emit ( c, Instruction :: encode_abc ( OpCode :: ShrI , result_reg, left_reg, imm) ) ;
245+ emit ( c, Instruction :: create_abck ( OpCode :: MmBinI , left_reg, imm_mmbini, TagMethod :: Shr . as_u32 ( ) , false ) ) ;
246+ Some ( result_reg)
247+ }
248+ BinaryOperator :: OpShl => {
249+ // x << n is equivalent to x >> -n
250+ let neg_imm = ( ( -int_val + 127 ) & 0xff ) as u32 ;
251+ emit ( c, Instruction :: encode_abc ( OpCode :: ShrI , result_reg, left_reg, neg_imm) ) ;
252+ emit ( c, Instruction :: create_abck ( OpCode :: MmBinI , left_reg, imm_mmbini, TagMethod :: Shl . as_u32 ( ) , false ) ) ;
253+ Some ( result_reg)
254+ }
255+ _ => None ,
256+ }
257+ }
258+
259+ /// Emit register-register binary operation with MMBIN
260+ pub fn emit_binop_rr (
261+ c : & mut Compiler ,
262+ op : BinaryOperator ,
263+ left_reg : u32 ,
264+ right_reg : u32 ,
265+ result_reg : u32 ,
266+ ) {
267+ let ( opcode, tm) = match op {
268+ BinaryOperator :: OpAdd => ( OpCode :: Add , Some ( TagMethod :: Add ) ) ,
269+ BinaryOperator :: OpSub => ( OpCode :: Sub , Some ( TagMethod :: Sub ) ) ,
270+ BinaryOperator :: OpMul => ( OpCode :: Mul , Some ( TagMethod :: Mul ) ) ,
271+ BinaryOperator :: OpDiv => ( OpCode :: Div , Some ( TagMethod :: Div ) ) ,
272+ BinaryOperator :: OpIDiv => ( OpCode :: IDiv , Some ( TagMethod :: IDiv ) ) ,
273+ BinaryOperator :: OpMod => ( OpCode :: Mod , Some ( TagMethod :: Mod ) ) ,
274+ BinaryOperator :: OpPow => ( OpCode :: Pow , Some ( TagMethod :: Pow ) ) ,
275+ BinaryOperator :: OpBAnd => ( OpCode :: BAnd , Some ( TagMethod :: BAnd ) ) ,
276+ BinaryOperator :: OpBOr => ( OpCode :: BOr , Some ( TagMethod :: BOr ) ) ,
277+ BinaryOperator :: OpBXor => ( OpCode :: BXor , Some ( TagMethod :: BXor ) ) ,
278+ BinaryOperator :: OpShl => ( OpCode :: Shl , Some ( TagMethod :: Shl ) ) ,
279+ BinaryOperator :: OpShr => ( OpCode :: Shr , Some ( TagMethod :: Shr ) ) ,
280+ _ => return ,
281+ } ;
282+
283+ emit ( c, Instruction :: encode_abc ( opcode, result_reg, left_reg, right_reg) ) ;
284+ if let Some ( tm) = tm {
285+ emit ( c, Instruction :: create_abck ( OpCode :: MmBin , left_reg, right_reg, tm. as_u32 ( ) , false ) ) ;
286+ }
287+ }
0 commit comments