%def binop(preinstr="" , result="w0" , chkzero=False, instr="" ):
/*
* Generic 32 - bit binary operation . Provide an " instr " line that
* specifies an instruction that performs " result = w0 op w1 " .
* This could be an ARM instruction or a function call . ( If the result
* comes back in a register other than w0 , you can override " result " . )
*
* If " chkzero " is set to 1 , we perform a divide - by - zero check on
* vCC ( w1 ) . Useful for integer division and modulus . Note that we
* * don ' t * check for ( INT_MIN / - 1 ) here , because the ARM math lib
* handles it correctly .
*
* For : add - int , sub - int , mul - int , div - int , rem - int , and - int , or - int ,
* xor - int , shl - int , shr - int , ushr - int , add - float , sub - float ,
* mul - float , div - float , rem - float
*/
/* binop vAA, vBB, vCC */
FETCH w0, 1 // w0<- CCBB
lsr w9, wINST, #8 // w9<- AA
lsr w3, w0, #8 // w3<- CC
and w2, w0, #255 // w2<- BB
GET_VREG w1, w3 // w1<- vCC
GET_VREG w0, w2 // w0<- vBB
% if chkzero:
cbz w1, common_errDivideByZero // is second operand zero?
FETCH_ADVANCE_INST 2 // advance rPC, load rINST
$preinstr // optional op; may set condition codes
$instr // $result<- op, w0-w3 changed
PREPARE_OPCODE_DISPATCH // insert opcode to xIBASE
SET_VREG $result, w9 // vAA<- $result
GOTO_OPCODE // jump to next instruction
/* 11-14 instructions */
%def binop2addr(preinstr="" , result="w0" , chkzero=False, instr="" ):
/*
* Generic 32 - bit " / 2 addr " binary operation . Provide an " instr " line
* that specifies an instruction that performs " result = w0 op w1 " .
* This could be an ARM instruction or a function call . ( If the result
* comes back in a register other than w0 , you can override " result " . )
*
* If " chkzero " is set to 1 , we perform a divide - by - zero check on
* vCC ( w1 ) . Useful for integer division and modulus .
*
* For : add - int / 2 addr , sub - int / 2 addr , mul - int / 2 addr , div - int / 2 addr ,
* rem - int / 2 addr , and - int / 2 addr , or - int / 2 addr , xor - int / 2 addr ,
* shl - int / 2 addr , shr - int / 2 addr , ushr - int / 2 addr , add - float / 2 addr ,
* sub - float / 2 addr , mul - float / 2 addr , div - float / 2 addr , rem - float / 2 addr
*/
/* binop/2addr vA, vB */
lsr w3, wINST, #12 // w3<- B
ubfx w9, wINST, #8 , #4 // w9<- A
GET_VREG w1, w3 // w1<- vB
GET_VREG w0, w9 // w0<- vA
% if chkzero:
cbz w1, common_errDivideByZero
FETCH_ADVANCE_INST 1 // advance rPC, load rINST
$preinstr // optional op; may set condition codes
$instr // $result<- op, w0-w3 changed
PREPARE_OPCODE_DISPATCH // insert opcode to xIBASE
SET_VREG $result, w9 // vAA<- $result
GOTO_OPCODE // jump to next instruction
/* 10-13 instructions */
%def binopLit16(preinstr="" , result="w0" , chkzero=False, instr="" ):
/*
* Generic 32 - bit " lit16 " binary operation . Provide an " instr " line
* that specifies an instruction that performs " result = w0 op w1 " .
* This could be an ARM instruction or a function call . ( If the result
* comes back in a register other than w0 , you can override " result " . )
*
* If " chkzero " is set to 1 , we perform a divide - by - zero check on
* vCC ( w1 ) . Useful for integer division and modulus .
*
* For : add - int / lit16 , rsub - int , mul - int / lit16 , div - int / lit16 ,
* rem - int / lit16 , and - int / lit16 , or - int / lit16 , xor - int / lit16
*/
/* binop/lit16 vA, vB, #+CCCC */
FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended)
lsr w2, wINST, #12 // w2<- B
ubfx w9, wINST, #8 , #4 // w9<- A
GET_VREG w0, w2 // w0<- vB
% if chkzero:
cbz w1, common_errDivideByZero
FETCH_ADVANCE_INST 2 // advance rPC, load rINST
$preinstr
$instr // $result<- op, w0-w3 changed
PREPARE_OPCODE_DISPATCH // insert opcode to xIBASE
SET_VREG $result, w9 // vAA<- $result
GOTO_OPCODE // jump to next instruction
/* 10-13 instructions */
%def binopLit8(extract="asr w1, w3, #8" , preinstr="" , result="w0" , chkzero=False, instr="" ):
/*
* Generic 32 - bit " lit8 " binary operation . Provide an " instr " line
* that specifies an instruction that performs " result = w0 op w1 " .
* This could be an ARM instruction or a function call . ( If the result
* comes back in a register other than w0 , you can override " result " . )
*
* You can override " extract " if the extraction of the literal value
* from w3 to w1 is not the default " asr w1 , w3 , # 8 " . The extraction
* can be omitted completely if the shift is embedded in " instr " .
*
* If " chkzero " is set to 1 , we perform a divide - by - zero check on
* vCC ( w1 ) . Useful for integer division and modulus .
*
* For : add - int / lit8 , rsub - int / lit8 , mul - int / lit8 , div - int / lit8 ,
* rem - int / lit8 , and - int / lit8 , or - int / lit8 , xor - int / lit8 ,
* shl - int / lit8 , shr - int / lit8 , ushr - int / lit8
*/
/* binop/lit8 vAA, vBB, #+CC */
FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC)
lsr w9, wINST, #8 // w9<- AA
and w2, w3, #255 // w2<- BB
GET_VREG w0, w2 // w0<- vBB
$extract // optional; typically w1<- ssssssCC (sign extended)
% if chkzero:
cbz w1, common_errDivideByZero
FETCH_ADVANCE_INST 2 // advance rPC, load rINST
$preinstr // optional op; may set condition codes
$instr // $result<- op, w0-w3 changed
PREPARE_OPCODE_DISPATCH // insert opcode to xIBASE
SET_VREG $result, w9 // vAA<- $result
GOTO_OPCODE // jump to next instruction
/* 10-12 instructions */
%def binopWide(preinstr="" , instr="add x0, x1, x2" , result="x0" , r1="x1" , r2="x2" , chkzero=False):
/*
* Generic 64 - bit binary operation . Provide an " instr " line that
* specifies an instruction that performs " result = x1 op x2 " .
* This could be an ARM instruction or a function call . ( If the result
* comes back in a register other than x0 , you can override " result " . )
*
* If " chkzero " is set to 1 , we perform a divide - by - zero check on
* vCC ( w1 ) . Useful for integer division and modulus .
*
* For : add - long , sub - long , mul - long , div - long , rem - long , and - long , or - long ,
* xor - long , add - double , sub - double , mul - double , div - double , rem - double
*/
/* binop vAA, vBB, vCC */
FETCH w0, 1 // w0<- CCBB
LOAD_SCALED_VREG_MASK w5, 0 xff // w5<- ff * sizeof(vreg)
EXTRACT_SCALED_VREG w4, w5, wINST, 8 // w4<- AA * sizeof(vreg)
EXTRACT_SCALED_VREG w2, w5, w0, 8 // w2<- CC * sizeof(vreg)
EXTRACT_SCALED_VREG w1, w5, w0, 0 // w1<- BB * sizeof(vreg)
GET_VREG_WIDE_PRESCALED $r2, w2 // w2<- vCC
GET_VREG_WIDE_PRESCALED $r1, w1 // w1<- vBB
% if chkzero:
cbz $r2, common_errDivideByZero // is second operand zero?
FETCH_ADVANCE_INST 2 // advance rPC, load rINST
$preinstr
$instr // $result<- op, w0-w4 changed
PREPARE_OPCODE_DISPATCH // insert opcode to xIBASE
SET_VREG_WIDE_PRESCALED $result, w4 // vAA<- $result
GOTO_OPCODE // jump to next instruction
/* 11-14 instructions */
%def binopWide2addr(preinstr="" , instr="add x0, x0, x1" , r0="x0" , r1="x1" , chkzero=False):
/*
* Generic 64 - bit " / 2 addr " binary operation . Provide an " instr " line
* that specifies an instruction that performs " x0 = x0 op x1 " .
* This must not be a function call , as we keep w2 live across it .
*
* If " chkzero " is set to 1 , we perform a divide - by - zero check on
* vCC ( w1 ) . Useful for integer division and modulus .
*
* For : add - long / 2 addr , sub - long / 2 addr , mul - long / 2 addr , div - long / 2 addr ,
* and - long / 2 addr , or - long / 2 addr , xor - long / 2 addr ,
* shl - long / 2 addr , shr - long / 2 addr , ushr - long / 2 addr , add - double / 2 addr ,
* sub - double / 2 addr , mul - double / 2 addr , div - double / 2 addr , rem - double / 2 addr
*/
/* binop/2addr vA, vB */
lsr w1, wINST, #12 // w1<- B
ubfx w2, wINST, #8 , #4 // w2<- A
GET_VREG_WIDE $r1, w1 // x1<- vB
GET_VREG_WIDE $r0, w2 // x0<- vA
% if chkzero:
cbz $r1, common_errDivideByZero
FETCH_ADVANCE_INST 1 // advance rPC, load rINST
$preinstr
$instr // result<- op
PREPARE_OPCODE_DISPATCH // insert opcode to xIBASE
SET_VREG_WIDE $r0, w2 // vAA<- result
GOTO_OPCODE // jump to next instruction
/* 10-13 instructions */
%def shiftWide(opcode="shl" ):
/*
* 64 - bit shift operation .
*
* For : shl - long , shr - long , ushr - long
*/
/* binop vAA, vBB, vCC */
FETCH w0, 1 // w0<- CCBB
lsr w3, wINST, #8 // w3<- AA
lsr w2, w0, #8 // w2<- CC
GET_VREG w2, w2 // w2<- vCC (shift count)
and w1, w0, #255 // w1<- BB
GET_VREG_WIDE x1, w1 // x1<- vBB
FETCH_ADVANCE_INST 2 // advance rPC, load rINST
$opcode x0, x1, x2 // Do the shift. Only low 6 bits of x2 are used.
PREPARE_OPCODE_DISPATCH // insert opcode to xIBASE
SET_VREG_WIDE x0, w3 // vAA<- x0
GOTO_OPCODE // jump to next instruction
/* 11-14 instructions */
%def shiftWide2addr(opcode="lsl" ):
/*
* Generic 64 - bit shift operation .
*/
/* binop/2addr vA, vB */
lsr w1, wINST, #12 // w1<- B
ubfx w2, wINST, #8 , #4 // w2<- A
GET_VREG w1, w1 // x1<- vB
GET_VREG_WIDE x0, w2 // x0<- vA
FETCH_ADVANCE_INST 1 // advance rPC, load rINST
$opcode x0, x0, x1 // Do the shift. Only low 6 bits of x1 are used.
PREPARE_OPCODE_DISPATCH // insert opcode to xIBASE
SET_VREG_WIDE x0, w2 // vAA<- result
GOTO_OPCODE // jump to next instruction
/* 10-13 instructions */
%def unop(instr="" ):
/*
* Generic 32 - bit unary operation . Provide an " instr " line that
* specifies an instruction that performs " result = op w0 " .
* This could be an ARM instruction or a function call .
*
* for : neg - int , not - int , neg - float , int - to - float , float - to - int ,
* int - to - byte , int - to - char , int - to - short
*/
/* unop vA, vB */
lsr w3, wINST, #12 // w3<- B
GET_VREG w0, w3 // w0<- vB
ubfx w9, wINST, #8 , #4 // w9<- A
FETCH_ADVANCE_INST 1 // advance rPC, load rINST
$instr // w0<- op, w0-w3 changed
PREPARE_OPCODE_DISPATCH // insert opcode to xIBASE
SET_VREG w0, w9 // vAA<- w0
GOTO_OPCODE // jump to next instruction
/* 8-9 instructions */
%def unopWide(instr="sub x0, xzr, x0" ):
/*
* Generic 64 - bit unary operation . Provide an " instr " line that
* specifies an instruction that performs " result = op x0 " .
*
* For : neg - long , not - long
*/
/* unop vA, vB */
lsr w3, wINST, #12 // w3<- B
ubfx w4, wINST, #8 , #4 // w4<- A
GET_VREG_WIDE x0, w3
FETCH_ADVANCE_INST 1 // advance rPC, load wINST
$instr
PREPARE_OPCODE_DISPATCH // insert opcode to xIBASE
SET_VREG_WIDE x0, w4
GOTO_OPCODE // jump to next instruction
/* 10-11 instructions */
%def op_add_int():
% binop(instr="add w0, w0, w1" )
%def op_add_int_2addr():
% binop2addr(instr="add w0, w0, w1" )
%def op_add_int_lit16():
% binopLit16(instr="add w0, w0, w1" )
%def op_add_int_lit8():
% binopLit8(extract="" , instr="add w0, w0, w3, asr #8" )
%def op_add_long():
% binopWide(instr="add x0, x1, x2" )
%def op_add_long_2addr():
% binopWide2addr(instr="add x0, x0, x1" )
%def op_and_int():
% binop(instr="and w0, w0, w1" )
%def op_and_int_2addr():
% binop2addr(instr="and w0, w0, w1" )
%def op_and_int_lit16():
% binopLit16(instr="and w0, w0, w1" )
%def op_and_int_lit8():
% binopLit8(extract="" , instr="and w0, w0, w3, asr #8" )
%def op_and_long():
% binopWide(instr="and x0, x1, x2" )
%def op_and_long_2addr():
% binopWide2addr(instr="and x0, x0, x1" )
%def op_cmp_long():
FETCH w0, 1 // w0<- CCBB
LOAD_SCALED_VREG_MASK w5, 0 xff // w4<- ff * sizeof(vreg)
lsr w4, wINST, #8 // w4<- AA
EXTRACT_SCALED_VREG w2, w5, w0, 0 // w2<- BB * sizeof(vreg)
EXTRACT_SCALED_VREG w3, w5, w0, 8 // w3<- CC * sizeof(vreg)
GET_VREG_WIDE_PRESCALED x1, w2
GET_VREG_WIDE_PRESCALED x2, w3
cmp x1, x2
cset w0, ne
cneg w0, w0, lt
FETCH_ADVANCE_INST 2 // advance rPC, load wINST
SET_VREG w0, w4
PREPARE_OPCODE_DISPATCH // insert opcode to xIBASE
GOTO_OPCODE // jump to next instruction
%def op_div_int():
% binop(instr="sdiv w0, w0, w1" , chkzero=True)
%def op_div_int_2addr():
% binop2addr(instr="sdiv w0, w0, w1" , chkzero=True)
%def op_div_int_lit16():
% binopLit16(instr="sdiv w0, w0, w1" , chkzero=True)
%def op_div_int_lit8():
% binopLit8(instr="sdiv w0, w0, w1" , chkzero=True)
%def op_div_long():
% binopWide(instr="sdiv x0, x1, x2" , chkzero=True)
%def op_div_long_2addr():
% binopWide2addr(instr="sdiv x0, x0, x1" , chkzero=True)
%def op_int_to_byte():
% unop(instr="sxtb w0, w0" )
%def op_int_to_char():
% unop(instr="uxth w0, w0" )
%def op_int_to_long():
/* int-to-long vA, vB */
lsr w3, wINST, #12 // w3<- B
ubfx w4, wINST, #8 , #4 // w4<- A
GET_VREG_S x0, w3 // x0<- sign_extend(fp[B])
FETCH_ADVANCE_INST 1 // advance rPC, load wINST
PREPARE_OPCODE_DISPATCH // insert opcode to xIBASE
SET_VREG_WIDE x0, w4 // fp[A]<- x0
GOTO_OPCODE // jump to next instruction
%def op_int_to_short():
% unop(instr="sxth w0, w0" )
%def op_long_to_int():
/* we ignore the high word, making this equivalent to a 32-bit reg move */
% op_move()
%def op_mul_int():
/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */
% binop(instr="mul w0, w1, w0" )
%def op_mul_int_2addr():
/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */
% binop2addr(instr="mul w0, w1, w0" )
%def op_mul_int_lit16():
/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */
% binopLit16(instr="mul w0, w1, w0" )
%def op_mul_int_lit8():
/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */
% binopLit8(instr="mul w0, w1, w0" )
%def op_mul_long():
% binopWide(instr="mul x0, x1, x2" )
%def op_mul_long_2addr():
% binopWide2addr(instr="mul x0, x0, x1" )
%def op_neg_int():
% unop(instr="sub w0, wzr, w0" )
%def op_neg_long():
% unopWide(instr="sub x0, xzr, x0" )
%def op_not_int():
% unop(instr="mvn w0, w0" )
%def op_not_long():
% unopWide(instr="mvn x0, x0" )
%def op_or_int():
% binop(instr="orr w0, w0, w1" )
%def op_or_int_2addr():
% binop2addr(instr="orr w0, w0, w1" )
%def op_or_int_lit16():
% binopLit16(instr="orr w0, w0, w1" )
%def op_or_int_lit8():
% binopLit8(extract="" , instr="orr w0, w0, w3, asr #8" )
%def op_or_long():
% binopWide(instr="orr x0, x1, x2" )
%def op_or_long_2addr():
% binopWide2addr(instr="orr x0, x0, x1" )
%def op_rem_int():
% binop(preinstr="sdiv w2, w0, w1" , instr="msub w0, w2, w1, w0" , chkzero=True)
%def op_rem_int_2addr():
% binop2addr(preinstr="sdiv w2, w0, w1" , instr="msub w0, w2, w1, w0" , chkzero=True)
%def op_rem_int_lit16():
% binopLit16(preinstr="sdiv w3, w0, w1" , instr="msub w0, w3, w1, w0" , chkzero=True)
%def op_rem_int_lit8():
% binopLit8(preinstr="sdiv w3, w0, w1" , instr="msub w0, w3, w1, w0" , chkzero=True)
%def op_rem_long():
% binopWide(preinstr="sdiv x3, x1, x2" , instr="msub x0, x3, x2, x1" , chkzero=True)
%def op_rem_long_2addr():
% binopWide2addr(preinstr="sdiv x3, x0, x1" , instr="msub x0, x3, x1, x0" , chkzero=True)
%def op_rsub_int():
/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
% binopLit16(instr="sub w0, w1, w0" )
%def op_rsub_int_lit8():
% binopLit8(instr="sub w0, w1, w0" )
%def op_shl_int():
% binop(instr="lsl w0, w0, w1" )
%def op_shl_int_2addr():
% binop2addr(instr="lsl w0, w0, w1" )
%def op_shl_int_lit8():
% binopLit8(extract="ubfx w1, w3, #8, #5" , instr="lsl w0, w0, w1" )
%def op_shl_long():
% shiftWide(opcode="lsl" )
%def op_shl_long_2addr():
% shiftWide2addr(opcode="lsl" )
%def op_shr_int():
% binop(instr="asr w0, w0, w1" )
%def op_shr_int_2addr():
% binop2addr(instr="asr w0, w0, w1" )
%def op_shr_int_lit8():
% binopLit8(extract="ubfx w1, w3, #8, #5" , instr="asr w0, w0, w1" )
%def op_shr_long():
% shiftWide(opcode="asr" )
%def op_shr_long_2addr():
% shiftWide2addr(opcode="asr" )
%def op_sub_int():
% binop(instr="sub w0, w0, w1" )
%def op_sub_int_2addr():
% binop2addr(instr="sub w0, w0, w1" )
%def op_sub_long():
% binopWide(instr="sub x0, x1, x2" )
%def op_sub_long_2addr():
% binopWide2addr(instr="sub x0, x0, x1" )
%def op_ushr_int():
% binop(instr="lsr w0, w0, w1" )
%def op_ushr_int_2addr():
% binop2addr(instr="lsr w0, w0, w1" )
%def op_ushr_int_lit8():
% binopLit8(extract="ubfx w1, w3, #8, #5" , instr="lsr w0, w0, w1" )
%def op_ushr_long():
% shiftWide(opcode="lsr" )
%def op_ushr_long_2addr():
% shiftWide2addr(opcode="lsr" )
%def op_xor_int():
% binop(instr="eor w0, w0, w1" )
%def op_xor_int_2addr():
% binop2addr(instr="eor w0, w0, w1" )
%def op_xor_int_lit16():
% binopLit16(instr="eor w0, w0, w1" )
%def op_xor_int_lit8():
% binopLit8(extract="" , instr="eor w0, w0, w3, asr #8" )
%def op_xor_long():
% binopWide(instr="eor x0, x1, x2" )
%def op_xor_long_2addr():
% binopWide2addr(instr="eor x0, x0, x1" )
Messung V0.5 in Prozent C=89 H=97 G=93
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-06-29)
¤
*© Formatika GbR, Deutschland