The Algorithms logo
The Algorithms
AboutDonate

2048

/* ===============================

   This program uses codes from Rosetta Code.
   See: https://rosettacode.org/wiki/2048
   This code follows Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

   =============================== */

/* ARM assembly AARCH64 Raspberry PI 3B */
/*  program 2048.s   */ 
 
/*******************************************/
/* Constantes file                         */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"
.equ SIZE,       4       
.equ TOTAL,      2048
.equ BUFFERSIZE, 80
 
.equ KEYSIZE,    8
.equ IOCTL,     0x1D  // Linux syscall
.equ SIGACTION, 0x86  // Linux syscall
.equ SYSPOLL,   0x16  // Linux syscall
.equ CREATPOLL, 0x14  // Linux syscall
.equ CTLPOLL,   0x15  // Linux syscall
 
.equ TCGETS,    0x5401
.equ TCSETS,    0x5402
.equ ICANON,    2
.equ ECHO,     10
.equ POLLIN,    1
.equ EPOLL_CTL_ADD,    1
 
.equ SIGINT,   2      // Issued if the user sends an interrupt signal (Ctrl + C)
.equ SIGQUIT,  3      // Issued if the user sends a quit signal (Ctrl + D)
.equ SIGTERM, 15      // Software termination signal (sent by kill by default)
.equ SIGTTOU, 22
 
/*******************************************/
/* Structures                               */
/********************************************/
/* structure termios see doc linux*/
    .struct  0
term_c_iflag:                    // input modes
    .struct  term_c_iflag + 4 
term_c_oflag:                    // output modes
    .struct  term_c_oflag + 4 
term_c_cflag:                    // control modes
    .struct  term_c_cflag + 4 
term_c_lflag:                    // local modes
    .struct  term_c_lflag + 4 
term_c_cc:                       // special characters
    .struct  term_c_cc + 40      // see length if necessary 
term_fin:
 
/* structure sigaction see doc linux */
    .struct  0
sa_handler:
    .struct  sa_handler + 8 
sa_mask:
    .struct  sa_mask + 8 
sa_flags:
    .struct  sa_flags + 8
sa_sigaction:
    .struct  sa_sigaction + 8
sa_fin:
 
/* structure poll see doc linux */
    .struct  0
poll_event:                        //  events mask
    .struct  poll_event + 8
poll_fd:                           // events returned
    .struct  poll_fd  + 8
poll_fin:
/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessOK:           .asciz "Bravo !! You win. \n"
szMessNotOK:        .asciz "You lost !! \n"
szMessNewGame:      .asciz "New game (y/n) ? \n"
szMessErreur:       .asciz "Error detected.\n"
szMessErrInitTerm:  .asciz "Error terminal init.\n"
szMessErrInitPoll:  .asciz "Error poll init.\n"
szMessErreurKey:    .asciz "Error read key.\n"
szMessErr:          .asciz    "Error code hexa : @ décimal : @ \n"
szCarriageReturn:   .asciz "\n"
szMess0:            .asciz "      "
szMess2:            .asciz "   2  "
szMess4:            .asciz "   4  "
szMess8:            .asciz "   8  "
szMess16:           .asciz "  16  "
szMess32:           .asciz "  32  "
szMess64:           .asciz "  64  "
szMess128:          .asciz " 128  "
szMess256:          .asciz " 256  "
szMess512:          .asciz " 512  "
szMess1024:         .asciz " 1024 "
szMess2048:         .asciz " 2048 "
szCleax1:           .byte 0x1B 
                    .byte 'c'           // other console clear
                    .byte 0
 
szLineH:            .asciz "-----------------------------\n"
szLineV:            .asciz "|"
szLineVT:           .asciz "|      |      |      |      |\n"
.align 4
qGraine:            .quad 123456
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
sZoneConv:      .skip 24
sBuffer:        .skip BUFFERSIZE
qTbCase:        .skip 8 * SIZE * SIZE
qEnd:           .skip 8                        // 0 loop  1 = end loop
qTouche:        .skip KEYSIZE                  // value key pressed
stOldtio:       .skip term_fin                 // old terminal state
stCurtio:       .skip term_fin                 // current terminal state
stSigAction:    .skip sa_fin                   // area signal structure
stSigAction1:   .skip sa_fin
stSigAction2:   .skip sa_fin
stSigAction3:   .skip sa_fin
stPoll1:        .skip poll_fin                 // area poll structure
stPoll2:        .skip poll_fin
stevents:       .skip 16
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                // entry of program 
    mov x0,#0
    bl initTerm                      // terminal init
    cmp x0,0                         // error ?
    blt 100f
    bl initPoll                      // epoll instance init
    cmp x0,0
    blt 99f
    mov x22,x0                        // save epfd
1:                                    // begin game loop
    ldr x0,qAdrszCleax1
    bl affichageMess
    bl razTable
2:
    bl addDigit   
    cmp x0,#-1
    beq 5f                            // end game
    bl displayGame
3:
    mov x0,x22
    bl waitKey
    cmp x0,0
    beq 3b
    bl readKey
    cmp x0,#-1
    beq 99f                          // error
    bl keyMove
    cmp x0,#0
    beq 3b                            // no change -> loop
    cmp x0,#2                         // last addition = 2048 ?
    beq 4f
    cmp x0,#-1                        // quit ?
    bne 2b                            // loop
 
    b 10f
4:                                    // last addition = 2048 
    ldr x0,qAdrszMessOK
    bl affichageMess
    b 10f
5:                                    // display message no solution
    ldr x0,qAdrszMessNotOK
    bl affichageMess
 
10:                                   // display new game ?
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    ldr x0,qAdrszMessNewGame
    bl affichageMess
11:
    mov x0,x22
    bl waitKey
    cmp x0,0
    beq 11b
    bl readKey
    ldr x0,qAdrqTouche
    ldrb w0,[x0]
    cmp w0,#'y'
    beq 1b
    cmp w0,#'Y'
    beq 1b
99:
    bl restauTerm                     // terminal restaur
100:                                  // standard end of the program 
    mov x0, #0                        // return code
    mov x8, #EXIT                     // request to exit program
    svc #0                            // perform the system call
 
qAdrszCarriageReturn:     .quad szCarriageReturn
qAdrszMessNotOK:          .quad szMessNotOK
qAdrszMessOK:             .quad szMessOK
qAdrszMessNewGame:        .quad szMessNewGame
qAdrsZoneConv:            .quad sZoneConv
qAdrszCleax1:             .quad szCleax1
qAdrszMessErrInitTerm:    .quad szMessErrInitTerm
qAdrszMessErrInitPoll:    .quad szMessErrInitPoll
qAdrszMessErreurKey:      .quad szMessErreurKey
qAdrstOldtio:             .quad stOldtio
qAdrstCurtio:             .quad stCurtio
qAdrstSigAction:          .quad stSigAction
qAdrstSigAction1:         .quad stSigAction1
qAdrSIG_IGN:              .quad 1
qAdrqEnd:                 .quad qEnd
qAdrqTouche:              .quad qTouche
qAdrstevents:             .quad stevents
/******************************************************************/
/*     raz table cases                                                   */ 
/******************************************************************/
razTable:
    stp x0,lr,[sp,-16]!     // save  registres
    stp x1,x2,[sp,-16]!     // save  registres
    ldr x1,qAdrqTbCase
    mov x2,#0
1:
    str xzr,[x1,x2,lsl #3]
    add x2,x2,#1
    cmp x2,#SIZE * SIZE
    blt 1b
100:
    ldp x1,x2,[sp],16       // restaur des  2 registres
    ldp x0,lr,[sp],16       // restaur des  2 registres
    ret
/******************************************************************/
/*     key move                                                   */ 
/******************************************************************/
/* x0 contains key value               */
keyMove:
    stp x1,lr,[sp,-16]!     // save  registres
    lsr x0,x0,#16
    cmp x0,#0x42                  // down arrow 
    bne 1f
    bl moveDown
    b 100f
1:
    cmp x0,#0x41                  // high arrow
    bne 2f
    bl moveUp
    b 100f
2:
    cmp x0,#0x43                  // right arrow
    bne 3f
    bl moveRight
    b 100f
3:
    cmp x0,#0x44                  // left arrow
    bne 4f
    bl moveLeft
    b 100f
4:
    ldr x0,qAdrqTouche
    ldrb w0,[x0]
    cmp w0,#'q'                   // quit game
    bne 5f
    mov x0,#-1
    b 100f
5:
    cmp w0,#'Q'                   // quit game
    bne 100f
    mov x0,#-1
    b 100f
 
100:
    ldp x1,lr,[sp],16       // restaur des  2 registres
    ret
/******************************************************************/
/*           move left                                   */ 
/******************************************************************/
/* x0 return -1 if ok     */
moveLeft:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    stp x8,x9,[sp,-16]!          // save  registres
    stp x10,x11,[sp,-16]!        // save  registres
    ldr x1,qAdrqTbCase
    mov x0,#0                   // top move Ok
    mov x2,#0                   // line indice
1:
    mov x6,#0                   // counter empty case
    mov x7,#0                   // first digit
    mov x10,#0                  // last digit to add
    mov x3,#0                   // column indice
2:
    lsl x5,x2,#2                // change this if size <> 4
    add x5,x5,x3                // compute table indice
    ldr x4,[x1,x5,lsl #3]
    cmp x4,#0
    cinc x6,x6,eq               // positions vides
    beq 5f
    cmp x6,#0
    beq 3f                      // no empty left case
    mov x8,#0
    str x8,[x1,x5,lsl #3]       // raz digit
    sub x5,x5,x6
    str x4,[x1,x5,lsl #3]       // and store to left empty position
    mov x0,#1                   // move Ok
3:
    cmp x7,#0                   // first digit
    beq 4f
    cmp x10,x4                  // prec digit have to add 
    beq 4f
    sub x8,x5,#1                // prec digit 
    ldr x9,[x1,x8,lsl #3]
    cmp x4,x9                   // equal ?
    bne 4f
    mov x10,x4                  // save digit 
    add x4,x4,x9                // yes -> add
    str x4,[x1,x8,lsl #3]
    cmp x4,#TOTAL
    beq 6f
    mov x4,#0
    str x4,[x1,x5,lsl #3]
    add x6,x6,#1                // empty case + 1
    mov x0,#1                   // move Ok
4:
    add x7,x7,#1                // no first digit
 
5:                              // and loop
    add x3,x3,#1
    cmp x3,#SIZE
    blt 2b
    add x2,x2,#1
    cmp x2,#SIZE
    blt 1b
    b 100f
6:
    mov x0,#2                   // total = 2048
100:
    ldp x10,x11,[sp],16         // restaur des  2 registres
    ldp x8,x9,[sp],16           // restaur des  2 registres
    ldp x6,x7,[sp],16           // restaur des  2 registres
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
/******************************************************************/
/*           move right                                   */ 
/******************************************************************/
/* x0 return -1 if ok     */
moveRight:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    stp x8,x9,[sp,-16]!          // save  registres
    stp x10,x11,[sp,-16]!        // save  registres
    ldr x1,qAdrqTbCase
    mov x0,#0
    mov x2,#0
1:
    mov x6,#0
    mov x7,#0
    mov x10,#0
    mov x3,#SIZE-1
2:
    lsl x5,x2,#2                  // change this if size <> 4
    add x5,x5,x3
    ldr x4,[x1,x5,lsl #3]
    cmp x4,#0
    cinc x6,x6,eq               // positions vides
    beq 5f
 
    cmp x6,#0
    beq 3f                      // no empty right case
    mov x0,#0
    str x0,[x1,x5,lsl #3]       // raz digit
    add x5,x5,x6
    str x4,[x1,x5,lsl #3]       // and store to right empty position
    mov x0,#1
3:
    cmp x7,#0                   // first digit
    beq 4f
    add x8,x5,#1                // next digit 
    ldr x9,[x1,x8,lsl #3]
    cmp x4,x9                   // equal ?
    bne 4f
    cmp x10,x4
    beq 4f
    mov x10,x4
    add x4,x4,x9                // yes -> add
    str x4,[x1,x8,lsl #3]
    cmp x4,#TOTAL
    beq 6f
    mov x4,#0
    str x4,[x1,x5,lsl #3]
    add x6,x6,#1                // empty case + 1
    mov x0,#1
4:
    add x7,x7,#1                // no first digit
 
5:                              // and loop
    sub x3,x3,#1
    cmp x3,#0
    bge 2b
    add x2,x2,#1
    cmp x2,#SIZE
    blt 1b
    b 100f
6:
    mov x0,#2
100:
    ldp x10,x11,[sp],16         // restaur des  2 registres
    ldp x8,x9,[sp],16           // restaur des  2 registres
    ldp x6,x7,[sp],16           // restaur des  2 registres
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
/******************************************************************/
/*           move down                                   */ 
/******************************************************************/
/* x0 return -1 if ok     */
moveDown:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    stp x8,x9,[sp,-16]!          // save  registres
    stp x10,x11,[sp,-16]!        // save  registres
    ldr x1,qAdrqTbCase
    mov x0,#0
    mov x3,#0
1:
    mov x6,#0
    mov x7,#0
    mov x10,#0
    mov x2,#SIZE-1
2:
    lsl x5,x2,#2                  // change this if size <> 4
    add x5,x5,x3
    ldr x4,[x1,x5,lsl #3]
    cmp x4,#0
    cinc x6,x6,eq               // positions vides
    beq 5f
    cmp x6,#0
    beq 3f                      // no empty right case
    mov x0,#0
    str x0,[x1,x5,lsl #3]       // raz digit
    lsl x0,x6,#2
    add x5,x5,x0
    str x4,[x1,x5,lsl #3]       // and store to right empty position
    mov x0,#1
3:
    cmp x7,#0                   // first digit
    beq 4f
    add x8,x5,#SIZE                // down digit 
    ldr x9,[x1,x8,lsl #3]
    cmp x4,x9                   // equal ?
    bne 4f
    cmp x10,x4
    beq 4f
    mov x10,x4
    add x4,x4,x9                // yes -> add
    str x4,[x1,x8,lsl #3]
    cmp x4,#TOTAL
    beq 6f
    mov x4,#0
    str x4,[x1,x5,lsl #3]
    add x6,x6,#1                // empty case + 1
    mov x0,#1
4:
    add x7,x7,#1                   // no first digit
 
5:                           // and loop
    sub x2,x2,#1
    cmp x2,#0
    bge 2b
    add x3,x3,#1
    cmp x3,#SIZE
    blt 1b
    b 100f
6:
    mov x0,#2
100:
    ldp x10,x11,[sp],16         // restaur des  2 registres
    ldp x8,x9,[sp],16           // restaur des  2 registres
    ldp x6,x7,[sp],16           // restaur des  2 registres
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
/******************************************************************/
/*           move up                                   */ 
/******************************************************************/
/* x0 return -1 if ok     */
moveUp:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    stp x6,x7,[sp,-16]!          // save  registres
    stp x8,x9,[sp,-16]!          // save  registres
    stp x10,x11,[sp,-16]!        // save  registres
    ldr x1,qAdrqTbCase
    mov x0,#0
    mov x3,#0
1:
    mov x6,#0
    mov x7,#0
    mov x10,#0
    mov x2,#0
2:
    lsl x5,x2,#2                  // change this if size <> 4
    add x5,x5,x3
    ldr x4,[x1,x5,lsl #3]
    cmp x4,#0
    cinc x6,x6,eq               // positions vides
    beq 5f
    cmp x6,#0
    beq 3f                      // no empty right case
    mov x0,#0
    str x0,[x1,x5,lsl #3]       // raz digit
    lsl x0,x6,#2
    sub x5,x5,x0
    str x4,[x1,x5,lsl #3]       // and store to right empty position
    mov x0,#1
3:
    cmp x7,#0                   // first digit
    beq 4f
    sub x8,x5,#SIZE             // up digit 
    ldr x9,[x1,x8,lsl #3]
    cmp x4,x9                   // equal ?
    bne 4f
    cmp x10,x4
    beq 4f
    mov x10,x4
    add x4,x4,x9                // yes -> add
    str x4,[x1,x8,lsl #3]
    cmp x4,#TOTAL
    beq 6f
    mov x4,#0
    str x4,[x1,x5,lsl #3]
    add x6,x6,#1                // empty case + 1
    mov x0,#1
4:
    add x7,x7,#1                // no first digit
 
5:                              // and loop
    add x2,x2,#1
    cmp x2,#SIZE
    blt 2b
    add x3,x3,#1
    cmp x3,#SIZE
    blt 1b
    b 100f
6:
    mov x0,#2
100:
    ldp x10,x11,[sp],16         // restaur des  2 registres
    ldp x8,x9,[sp],16           // restaur des  2 registres
    ldp x6,x7,[sp],16           // restaur des  2 registres
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
/******************************************************************/
/*           add new digit on game                                   */ 
/******************************************************************/
/* x0 return -1 if ok     */
addDigit:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    stp x4,x5,[sp,-16]!          // save  registres
    sub sp,sp,#8 * SIZE*SIZE
    mov fp,sp
 
    mov x0,#100
    bl genereraleas
    cmp x0,#10
    mov x1,#4
    mov x5,#2
    csel x5,x5,x1,ge
   // movlt x5,#4
    //movge x5,#2
    ldr x1,qAdrqTbCase
    mov x3,#0
    mov x4,#0
1:  
    ldr x2,[x1,x3,lsl 3]
    cmp x2,#0
    bne 2f
    str x3,[fp,x4,lsl 3]
    add x4,x4,#1
2:
    add x3,x3,#1
    cmp x3,#SIZE*SIZE
    blt 1b
    cmp x4,#0                 // no empty case
    beq 4f
    cmp x4,#1
    bne 3f
    ldr x2,[fp]               // one case
    str x5,[x1,x2,lsl 3]
    mov x0,#0
    b 100f
3:                            // multiple case
    sub x0,x4,#1
    bl genereraleas
    ldr x2,[fp,x0,lsl 3]
    str x5,[x1,x2,lsl 3]
    mov x0,#0
    b 100f
4:
    mov x0,#-1
100:
    add sp,sp,#8*  (SIZE*SIZE)  // stack alignement
    ldp x4,x5,[sp],16           // restaur des  2 registres
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
qAdrqTbCase:         .quad qTbCase
/******************************************************************/
/*            display game                                      */ 
/******************************************************************/
displayGame:
    stp x1,lr,[sp,-16]!          // save  registres
    stp x2,x3,[sp,-16]!          // save  registres
    ldr x0,qAdrszCleax1
    bl affichageMess
    ldr x0,qAdrszLineH
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
    ldr x1,qAdrqTbCase
    mov x2,#0
1:
    ldr x0,[x1,x2,lsl #3]
    bl digitString
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
    add x2,x2,#1
    cmp x2,#SIZE
    blt 1b
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineH
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
2:
    ldr x0,[x1,x2,lsl #3]
    bl digitString
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
    add x2,x2,#1
    cmp x2,#SIZE*2
    blt 2b
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineH
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
3:
    ldr x0,[x1,x2,lsl #3]
    bl digitString
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
    add x2,x2,#1
    cmp x2,#SIZE*3
    blt 3b
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineH
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
4:
    ldr x0,[x1,x2,lsl #3]
    bl digitString
    bl affichageMess
    ldr x0,qAdrszLineV
    bl affichageMess
    add x2,x2,#1
    cmp x2,#SIZE*4
    blt 4b
    ldr x0,qAdrszCarriageReturn
    bl affichageMess
    ldr x0,qAdrszLineVT
    bl affichageMess
    ldr x0,qAdrszLineH
    bl affichageMess
 
100:
    ldp x2,x3,[sp],16           // restaur des  2 registres
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
qAdrszLineH:         .quad szLineH
qAdrszLineV:         .quad szLineV
qAdrszLineVT:        .quad szLineVT
/******************************************************************/
/*            digits string                                       */ 
/******************************************************************/
/* x0 contains number */
/* x0 return address string */
digitString:
    stp x1,lr,[sp,-16]!          // save  registres
    cmp x0,#0
    bne 1f
    ldr x0,qAdrszMess0
    b 100f
1:
    cmp x0,#2
    bne 2f
    ldr x0,qAdrszMess2
    b 100f
2:
    cmp x0,#4
    bne 3f
    ldr x0,qAdrszMess4
    b 100f
3:
    cmp x0,#8
    bne 4f
    ldr x0,qAdrszMess8
    b 100f
4:
    cmp x0,#16
    bne 5f
    ldr x0,qAdrszMess16
    b 100f
5:
    cmp x0,#32
    bne 6f
    ldr x0,qAdrszMess32
    b 100f
6:
    cmp x0,#64
    bne 7f
    ldr x0,qAdrszMess64
    b 100f
7:
    cmp x0,#128
    bne 8f
    ldr x0,qAdrszMess128
    b 100f
8:
    cmp x0,#256
    bne 9f
    ldr x0,qAdrszMess256
    b 100f
9:
    cmp x0,#512
    bne 10f
    ldr x0,qAdrszMess512
    b 100f
10:
    cmp x0,#1024
    bne 11f
    ldr x0,qAdrszMess1024
    b 100f
11:
    cmp x0,#2048
    bne 12f
    ldr x0,qAdrszMess2048
    b 100f
12:
    ldr x1,qAdrszMessErreur                       // error message
    bl   displayError
100:
    ldp x1,lr,[sp],16           // restaur des  2 registres
    ret
qAdrszMess0:          .quad szMess0
qAdrszMess2:          .quad szMess2
qAdrszMess4:          .quad szMess4
qAdrszMess8:          .quad szMess8
qAdrszMess16:         .quad szMess16
qAdrszMess32:         .quad szMess32
qAdrszMess64:         .quad szMess64
qAdrszMess128:        .quad szMess128
qAdrszMess256:        .quad szMess256
qAdrszMess512:        .quad szMess512
qAdrszMess1024:       .quad szMess1024
qAdrszMess2048:        .quad szMess2048
 
//qAdrsBuffer:         .quad sBuffer
qAdrszMessErreur :        .quad szMessErreur 
 
/***************************************************/
/*   Generation random number                  */
/***************************************************/
/* x0 contains limit  */
genereraleas:
    stp x1,lr,[sp,-16]!            // save  registers
    stp x2,x3,[sp,-16]!            // save  registers
    ldr x1,qAdrqGraine
    ldr x2,[x1]
    ldr x3,qNbDep1
    mul x2,x3,x2
    ldr x3,qNbDep2
    add x2,x2,x3
    str x2,[x1]                    // maj de la graine pour l appel suivant 
    cmp x0,#0
    beq 100f
    udiv x3,x2,x0
    msub x0,x3,x0,x2               // résult = remainder
 
100:                               // end function
    ldp x2,x3,[sp],16              // restaur  2 registers
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/*****************************************************/
qAdrqGraine: .quad qGraine
qNbDep1:     .quad 0x0019660d
qNbDep2:     .quad 0x3c6ef35f
 
/******************************************************************/
/*     traitement du signal                                       */ 
/******************************************************************/
sighandler:
    stp x0,lr,[sp,-16]!            // save  registers
    str x1,[sp,-16]! 
    ldr x0,qAdrqEnd
    mov x1,#1                      // maj zone end
    str x1,[x0]
    ldr x1,[sp],16
    ldp x0,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/***************************************************/
/*   display error message                         */
/***************************************************/
/* x0 contains error code  x1 : message address */
displayError:
    stp x2,lr,[sp,-16]!            // save  registers
    mov x2,x0                      // save error code
    mov x0,x1
    bl affichageMess
    mov x0,x2                      // error code
    ldr x1,qAdrsZoneConv
    bl conversion16                // conversion hexa
    ldr x0,qAdrszMessErr           // display error message
    ldr x1,qAdrsZoneConv
    bl strInsertAtCharInc               // insert result at @ character
    mov x3,x0
    mov x0,x2                      // error code
    ldr x1,qAdrsZoneConv               // result address
    bl conversion10S                // conversion decimale
    mov x0,x3
    ldr x1,qAdrsZoneConv
    bl strInsertAtCharInc               // insert result at @ character
    bl affichageMess
100:
    ldp x2,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
qAdrszMessErr:                 .quad szMessErr
/*********************************/
/* init terminal state            */
/*********************************/
initTerm:
    stp x1,lr,[sp,-16]!            // save  registers
    /* read terminal state */
    mov x0,STDIN                   // input console
    mov x1,TCGETS
    ldr x2,qAdrstOldtio
    mov x8,IOCTL                   // call system Linux
    svc 0 
    cbnz x0,98f                    // error ?
 
    adr x0,sighandler              // adresse routine traitement signal
    ldr x1,qAdrstSigAction         // adresse structure sigaction
    str x0,[x1,sa_handler]         // maj handler
    mov x0,SIGINT                  // signal type
    ldr x1,qAdrstSigAction
    mov x2,0
    mov x3,8
    mov x8,SIGACTION               // call system
    svc 0 
 
    cmp x0,0                       // error ?
    bne 98f
    mov x0,SIGQUIT
    ldr x1,qAdrstSigAction
    mov x2,0                       // NULL
    mov x8,SIGACTION               // call system 
    svc 0 
    cmp x0,0                       // error ?
    bne 98f
    mov x0,SIGTERM
    ldr x1,qAdrstSigAction
    mov x2,0                       // NULL
    mov x8,SIGACTION               // appel systeme 
    svc 0 
    cmp x0,0
    bne 98f
    //
    adr x0,qAdrSIG_IGN             // address signal igonre function
    ldr x1,qAdrstSigAction1
    str x0,[x1,sa_handler]
    mov x0,SIGTTOU                 //invalidate other process signal
    ldr x1,qAdrstSigAction1
    mov x2,0                       // NULL
    mov x8,SIGACTION               // call system 
    svc 0 
    cmp x0,0
    bne 98f
    //
    /* read terminal current state  */
    mov x0,STDIN
    mov x1,TCGETS
    ldr x2,qAdrstCurtio            // address current termio
    mov x8,IOCTL                   // call systeme 
    svc 0 
    cmp x0,0                       // error ?
    bne 98f
    mov x2,ICANON | ECHO           // no key pressed echo on display
    mvn x2,x2                      // and one key 
    ldr x1,qAdrstCurtio
    ldr x3,[x1,#term_c_lflag]
    and x3,x2,x2                   // add flags 
    str x3,[x1,#term_c_lflag]      // and store
    mov x0,STDIN                   // maj terminal current state 
    mov x1,TCSETS
    ldr x2,qAdrstCurtio
    mov x8,IOCTL                   // call system
    svc 0 
    cbz x0,100f
98:                                // error display
    ldr x1,qAdrszMessErrInitTerm
    bl   displayError
    mov x0,-1
100:
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
qAdrstSigAction2:    .quad stSigAction2
qAdrstSigAction3:    .quad stSigAction3
/*********************************/
/* init instance epool            */
/*********************************/
initPoll:
    stp x1,lr,[sp,-16]!            // save  registers
    ldr x0,qAdrstevents
    mov x1,STDIN                   // maj structure events
    str x1,[x0,#poll_fd]           // maj FD
    mov x1,POLLIN                  // action code
    str x1,[x0,#poll_event]
    mov x0,0
    mov x8,CREATPOLL               // create epoll instance
    svc 0
    cmp x0,0                       // error ?
    ble 98f
    mov x10,x0                     // return FD epoll instance
    mov x1,EPOLL_CTL_ADD
    mov x2,STDIN                   // Fd to we want add
    ldr x3,qAdrstevents            // structure events address
    mov x8,CTLPOLL                 // call system control epoll
    svc 0
    cmp x0,0                       // error ?
    blt 98f                       // no
    mov x0,x10                     // return FD epoll instance
    b 100f
98:                                // error display
    ldr x1,qAdrszMessErrInitPoll   // error message
    bl   displayError
    mov x0,-1
100:
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/*********************************/
/* wait key                      */
/*********************************/
/* x0 contains FD poll    */
waitKey:
    stp x1,lr,[sp,-16]!            // save  registers
    ldr x11,qAdrqTouche            // key address
    str xzr,[x11]                  // raz key
1:
    ldr x1,qAdrqEnd                // if signal ctrl-c  -> end
    ldr x1,[x1]
    cbnz x1,100f
 
    ldr x1,qAdrstevents
    mov x2,12                      // size events
    mov x3,1                       // timeout = 1  TODO: ??
    mov x4,0
    mov x8,SYSPOLL                 // call system wait POLL
    svc 0 
    cmp x0,0                       // key pressed ?
    bge 100f
98:                                // error display
    ldr x1,qAdrszMessErreurKey        // error message
    bl   displayError
    mov x0,-1
100:
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/*********************************/
/* read key                      */
/*********************************/
/* x0 returns key value */
readKey:
    stp x1,lr,[sp,-16]!            // save  registers
    mov x0,STDIN                   // File Descriptor
    ldr x1,qAdrqTouche             // buffer address
    mov x2,KEYSIZE                 // key size
    mov x8,READ                    // read key
    svc #0
    cmp x0,0                       // error ?
    ble 98f
    ldr x2,qAdrqTouche             // key address
    ldr x0,[x2]
    b 100f
98:                                // error display
    ldr x1,qAdrszMessErreur        // error message
    bl   displayError
    mov x0,-1
100:
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/*********************************/
/* restaur terminal state        */
/*********************************/
restauTerm:
    stp x1,lr,[sp,-16]!            // save  registers
    mov x0,STDIN                   // end then restaur begin state terminal
    mov x1,TCSETS
    ldr x2,qAdrstOldtio
    mov x8,IOCTL                   // call system  
    svc 0
    cbz x0,100f
    ldr x1,qAdrszMessErreur        // error message
    bl   displayError
100:
    ldp x1,lr,[sp],16              // restaur  2 registers
    ret                            // return to address lr x30
/********************************************************/
/*        File Include fonctions                        */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"