25519P          = big_exp( 02, hex(255) )
25519p          = big_sub( $25519p, hex(19))

// d = -121665/121666
tmp             = hex(121665)
tmp             = big_sub( $25519p, $tmp )
tmp1            = hex(121666)
tmp1            = big_mod_inv( $tmp1, $25519p )
curve25519_d    = big_mod_mul( $tmp, $tmp1, $25519p )

bx              = 216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A
by              = 6666666666666666666666666666666666666666666666666666666666666658
bz              = 0000000000000000 0000000000000000 0000000000000000 0000000000000001
// t = x * y / z
bt              = big_mod_mul( $bx, $by, $25519p )

k               = 9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60
k               = sha512_hash( $k )
k               = left( $k, 32 )
k               = memand( $k, 00, f8 )
k               = memand( $k, 1f, 3f )
k               = memor( $k, 1f, 40 )

clear_fifo

// k = 0000000000000000 0000000000000000 0000000000000000 0000000000000003

prompt off
call kp( $k, $bx, $by, $bz, $bt )
prompt on


rx              = read_fifo
ry              = read_fifo
rz              = read_fifo
rt              = read_fifo

t               = call compressp( $rx, $ry, $rz )
t               = reverse_block_byte( $t )

end

kp:
    
inputk  = getpara
    
px      = getpara
    
py      = getpara
    
pz      = getpara
    
pt      = getpara

    
qx      = 0000000000000000 0000000000000000 0000000000000000 0000000000000000
    
qy      = 0000000000000000 0000000000000000 0000000000000000 0000000000000001
    
qz      = 0000000000000000 0000000000000000 0000000000000000 0000000000000001
    
qt      = 0000000000000000 0000000000000000 0000000000000000 0000000000000000

    
//  ? "第一种写法, 从右向左扫描"
    //  inputk  = reverse_block_byte( $inputk )

    
// again:
    //  if $inputk > 00

    
//      bit = getbit_right( $inputk, 1f, 00, 00 )

    
//      if $bit == 01
    //          clear_fifo

    
//          call addp( $qx, $qy, $qz, $qt, $px, $py, $pz, $pt )
    //          qx  = read_fifo
    //          qy  = read_fifo
    //          qz  = read_fifo
    //          qt  = read_fifo
    //      endif

    
//      clear_fifo

    
//      call addp( $px, $py, $pz, $pt, $px, $py, $pz, $pt )


    
//      px      = read_fifo
    //      py      = read_fifo
    //      pz      = read_fifo
    //      pt      = read_fifo

    
//      inputk  = shr( $inputk, 01 )
    //  else
    //      goto out
    //  endif
    //  goto again

    
// out:

    
? "第二种写法,从右到左扫描,没有移位操作"
    
flag    = 00
    
hfor i = ff to 00 step -01
        
byte_off    = div( $i, 08 )
        
bit_off     = mod( $i, 08 )
        
//bit_off = sub( 07, $bit_off )

        
bit         = getbit_right( $inputk, $byte_off, $bit_off, $bit_off )

        
if $bit == 01
            
flag    = 01
        
endif

        
if $flag == 01
            
clear_fifo
            
call addp( $qx, $qy, $qz, $qt, $qx, $qy, $qz, $qt )
            
qx  = read_fifo
            
qy  = read_fifo
            
qz  = read_fifo
            
qt  = read_fifo

            
if $bit == 01
                
clear_fifo

                
call addp( $qx, $qy, $qz, $qt, $px, $py, $pz, $pt )

                
qx  = read_fifo
                
qy  = read_fifo
                
qz  = read_fifo
                
qt  = read_fifo
            
endif
        
endif
    
hnext i

    
clear_fifo
    
write_fifo $qx
    
write_fifo $qy
    
write_fifo $qz
    
write_fifo $qt

return


doublep:
    
x1  = getpara
    
y1  = getpara
    
z1  = getpara
    
t1  = getpara

    
// a = x1^2

    
a   = big_mod_mul( $x1, $x1, $25519p )
    
a   = leftpack( $a, 32 )

    
// b = y1^2

    
b   = big_mod_mul( $y1, $y1, $25519p )
    
b   = leftpack( $b, 32 )

    
// c = 2*z1^2
    c   = big_mod_mul( $z1, $z1, $25519p )
    
c   = leftpack( $c, 32 )
    
c   = big_mod_add( $c, $c, $25519p )
    
c   = leftpack( $c, 32 )

    
// h = a + b

    
h   = big_mod_add( $a, $b, $25519p )
    
h   = leftpack( $h, 32 )

    
// e = h - (X1 + Y1)^2
    e   = big_mod_add( $x1, $y1, $25519p )
    
e   = leftpack( $e, 32 )
    
e   = big_mod_mul( $e, $e, $25519p )
    
e   = leftpack( $e, 32 )
    
e   = big_mod_sub( $h, $e, $25519p )
    
e   = leftpack( $e, 32 )

    
// g = a - b
    g   = big_mod_sub( $a, $b, $25519p )
    
g   = leftpack( $g, 32 )

    
// h = c + g
    h   = big_mod_add( $c, $g, $25519p )
    
h   = leftpack( $h, 32 )

    
// x3 = e * f
    x3  = big_mod_mul( $e, $f, $25519p )
    
x3  = leftpack( $x3, 32 )

    
// y3 = g * h
    y3  = big_mod_mul( $g, $h, $25519p )
    
y3  = leftpack( $y3, 32 )

    
// t3 = e * h
    t3  = big_mod_mul( $e, $h, $25519p )
    
t3  = leftpack( $t3, 32 )

    
// z3 = f * g
    z3  = big_mod_mul( $f, $g, $25519p )
    
z3  = leftpack( $z3, 32 )

    
clear_fifo

    
write_fifo $x3
    
write_fifo $y3
    
write_fifo $z3
    
write_fifo $t3

return

addp:
    
x1  = getpara
    
y1  = getpara
    
z1  = getpara
    
t1  = getpara
    
x2  = getpara
    
y2  = getpara
    
z2  = getpara
    
t2  = getpara

    
// a = (y1-x1)*(y2-x2)
    c   = big_mod_sub( $y1, $x1, $25519p )
    
c   = leftpack( $c, 32 )
    
d   = big_mod_sub( $y2, $x2, $25519p )
    
d   = leftpack( $d, 32 )
    
a   = big_mod_mul( $c, $d, $25519p )
    
a   = leftpack( $a, 32 )

    
// B = (Y1 + X1) * (Y2 + X2)
    c   = big_mod_add( $y1, $x1, $25519p )
    
c   = leftpack( $c, 32 )
    
d   = big_mod_add( $y2, $x2, $25519p )
    
d   = leftpack( $d, 32 )
    
b   = big_mod_mul( $c, $d, $25519p )
    
b   = leftpack( $b, 32 )

    
// C = t1*2*d*t2
    c   = big_mod_mul( $t1, 02, $25519p )
    
c   = leftpack( $c, 32 )
    
c   = big_mod_mul( $c, $curve25519_d, $25519p )
    
c   = leftpack( $c, 32 )
    
c   = big_mod_mul( $c, $t2, $25519p )
    
c   = leftpack( $c, 32 )

    
// d =z1 *2 * z2
    d   = big_mod_mul( $z1, $z2, $25519p )
    
d   = leftpack( $d, 32 )
    
d   = big_mod_mul( $d, 02, $25519p )
    
d   = leftpack( $d, 32 )

    
// e = b-a

    
e   = big_mod_sub( $b, $a, $25519p )
    
e   = leftpack( $e, 32 )

    
// f = d - c
    f   = big_mod_sub( $d, $c, $25519p )
    
f   = leftpack( $f, 32 )

    
// g = d + c
    g   = big_mod_add( $d, $c, $25519p )
    
g   = leftpack( $g, 32 )

    
// h = b + a
    h   = big_mod_add( $b, $a, $25519p )
    
h   = leftpack( $h, 32 )

    
// x3 = e*f

    
x3  = big_mod_mul( $e, $f, $25519p )
    
x3  = leftpack( $x3, 32 )

    
// y3 = g*h

    
y3  = big_mod_mul( $g, $h, $25519p )
    
y3  = leftpack( $y3, 32 )

    
// z3 = f*g

    
z3  = big_mod_mul( $f, $g, $25519p )
    
z3  = leftpack( $z3, 32 )

    
// t3 = e*h

    
t3  = big_mod_mul( $e, $h, $25519p )
    
t3  = leftpack( $t3, 32 )

    
//  ? "point add"
    //  ? "a  = " $a

    
//  ? "b  = " $b

    
//  ? "c  = " $c

    
//  ? "d  = " $d

    
//  ? "e  = " $e

    
//  ? "f  = " $f

    
//  ? "g  = " $g

    
//  ? "h  = " $h

    
//  ? "x3 = " $x3
    //  ? "y3 = " $y3
    //  ? "z3 = " $z3
    //  ? "t3 = " $t3
    clear_fifo

    
write_fifo $x3
    
write_fifo $y3
    
write_fifo $z3
    
write_fifo $t3

return

compressp:
    
inx     = getpara
    
iny     = getpara
    
inz     = getpara

    
zinv    = big_mod_inv( $inz, $25519p )

    
x       = big_mod_mul( $inz, $zinv, $25519p )
    
if $x != 00000001
        
?
        
pause
    
endif

    
tmpx    = big_mod_mul( $inx, $zinv, $25519p )
    
tmpy    = big_mod_mul( $iny, $zinv, $25519p )

    
bit     = getbit_right( $tmpx, 1f, 00, 00 )
    
bit     = shl( $bit, 255 )

    
tmpy    = or( $tmpy, $bit )

return $tmpy