Guest User

Sipeed MaixシリーズのArduino用のRISC-V RV64GCインラインアセンブラ デモプログラム(倍精度浮動小数点修正版)

a guest
Nov 3rd, 2020
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.98 KB | None | 0 0
  1. //  PlatformIO IDEでビルドする場合はplatformio.iniに
  2. //  下記オプションのいずれかを指定してください
  3. //
  4. // build_unflags = -march=rv64imafc
  5. // build_flags = -mabi=lp64f -march=rv64gc
  6. //
  7. // build_unflags = -Os -march=rv64imafc
  8. // build_flags = -O2 -mabi=lp64f -march=rv64gc
  9. //
  10. // build_unflags = -Os -march=rv64imafc
  11. // build_flags = -O3 -mabi=lp64f -march=rv64gc
  12.  
  13. // Arduino IDEでビルドする場合は下記のやり方でオプションを変更してください
  14. // (オプション変更に関しては自己責任でお願いします)
  15. // https://pastebin.com/E66j9e7f
  16. //
  17.  
  18. #include <Arduino.h>
  19. #include <math.h>
  20.  
  21. #include <Sipeed_ST7789.h>
  22. SPIClass spi0(SPI0); // MUST be SPI0 for Maix series on board LCD
  23. Sipeed_ST7789 lcd(320, 240, spi0);
  24.  
  25. extern "C" {
  26.     void print_number_x_y(int x, int y);
  27.     void print_number_x_y_double(double x, double y);
  28.     void line(int x1, int y1, int x2, int y2, int colr, int colg, int colb);
  29.     double sin01(double a);
  30.     double cos01(double a);
  31.     int random01(int min, int max);
  32.     void delay01(int ms);
  33.     void lcd_clear01(void);
  34.  
  35.     double rad01 = M_PI / 180.0;;
  36.     int width01 = 320;
  37.     int height01 = 240;
  38. }
  39.  
  40. void setup() {
  41.     lcd.begin(15000000, COLOR_BLACK);
  42.     lcd.fillRect(0, 0, 320, 240, COLOR_BLACK);
  43.  
  44.     Serial.begin(115200);
  45. }
  46.  
  47. int func01(int a, int b);
  48. int func01_asm(int a, int b);
  49. void loop() {
  50.     for (int i = 1; i < 8; i += 2) {
  51.         func01_asm(i, i + 1);
  52.         delay(5000);
  53.     }
  54. }
  55.    
  56. int func01(int a, int b){
  57.  
  58.     int    i, x1, y1, x2, y2, colr, colg, colb;
  59.     double   f1, f2, x, y, ra, rb, xc, yc;
  60.  
  61.     lcd_clear01();
  62.     colr = random01(16, 31);
  63.     colg = random01(16, 63);
  64.     colb = random01(16, 31);
  65.     ra = width01 / 2 - 10;
  66.     rb = height01 / 2 - 10;
  67.     xc = width01 / 2;
  68.     yc = height01 / 2;
  69.     for (i = 0; i < 360; i++) {
  70.         f1 = i * a * rad01;
  71.         x = ra * cos01(f1) + xc;
  72.         f2 = i * b * rad01;
  73.         y = rb * sin01(f2) + yc;
  74.         x1 = x;
  75.         y1 = y;
  76.         if (i == 0) {
  77.             x2 = x1;
  78.             y2 = y1;
  79.         }
  80.         line(x1, y1, x2, y2, colr, colg, colb);        
  81.         print_number_x_y(x1, y1);
  82.         x2 = x1;
  83.         y2 = y1;
  84.         delay01(10);
  85.     }
  86.     return 0;
  87. }
  88.  
  89. int func01_asm(int a, int b){
  90.    
  91.     asm volatile(
  92.                 "addi    sp, sp, -48\n\t"
  93.  
  94. /*                
  95.                  s8          x1
  96.                  s1          y1
  97.                  s2          x2
  98.                  s3          y2
  99.                  s4           i
  100.                  s5          colr
  101.                  s6          colg
  102.                  s7          colb
  103.                  fs2         ra
  104.                  fs3         rb
  105.                  fs4         xc
  106.                  fs5         yc
  107.                  0(sp)       a
  108.                  4(sp)       b
  109.                  8(sp)       &rad01
  110.                  16(sp)      &width01
  111.                  24(sp)      &height01
  112. */
  113.                  "sw      %0,   0(sp)\n\t"    // 関数呼び出しで%0が破壊されるので保存
  114.                  "sw      %1,   4(sp)\n\t"    // 関数呼び出しで%1が破壊されるので保存
  115.                  "sd      %2,   8(sp)\n\t"    // 関数呼び出しで%2が破壊されるので保存
  116.                  "sd      %3,   16(sp)\n\t"   // 関数呼び出しで%3が破壊されるので保存
  117.                  "sd      %4,   24(sp)\n\t"   // 関数呼び出しで%4が破壊されるので保存
  118.                
  119.                  "call    lcd_clear01\n\t"
  120.  
  121.                  "li      a0, 16\n\t"
  122.                  "li      a1, 31\n\t"
  123.                  "call    random01\n\t"
  124.                  "move    s5, a0\n\t"
  125.  
  126.                  "li      a0, 16\n\t"
  127.                  "li      a1, 63\n\t"
  128.                  "call    random01\n\t"
  129.                  "move    s6, a0\n\t"
  130.  
  131.                  "li      a0, 16\n\t"
  132.                  "li      a1, 31\n\t"
  133.                  "call    random01\n\t"
  134.                  "move    s7, a0\n\t"
  135.  
  136.                  "ld      a0, 16(sp)\n\t"
  137.                  "lw      a0, (a0)\n\t"
  138.                  "sraiw   a0, a0, 1\n\t"
  139.                  "li      a1, 10\n\t"
  140.                  "subw     a0, a0, a1\n\t"
  141.                  "fcvt.d.w  fs2, a0\n\t"
  142.  
  143.                  "ld      a0, 24(sp)\n\t"
  144.                  "lw      a0, (a0)\n\t"
  145.                  "sraiw   a0, a0, 1\n\t"
  146.                  "li      a1, 10\n\t"
  147.                  "subw     a0, a0, a1\n\t"
  148.                  "fcvt.d.w  fs3, a0\n\t"
  149.  
  150.                  "ld      a0, 16(sp)\n\t"
  151.                  "lw      a0, (a0)\n\t"
  152.                  "sraiw   a0, a0, 1\n\t"
  153.                  "fcvt.d.w  fs4, a0\n\t"
  154.                  
  155.                  "ld      a0, 24(sp)\n\t"
  156.                  "lw      a0, (a0)\n\t"
  157.                  "sraiw   a0, a0, 1\n\t"
  158.                  "fcvt.d.w  fs5, a0\n\t"
  159.  
  160.                  "move    s4, zero\n\t"
  161.     "loop01:\n\t "
  162.                  "li      a0, 360\n\t"
  163.                  "bge     s4, a0, jump01\n\t"
  164.  
  165.                  "lw      a0, 0(sp)\n\t"
  166.                  "mulw     a0, s4, a0\n\t"
  167.                  "fcvt.d.w  fa0, a0\n\t"
  168.                  "ld      a0, 8(sp)\n\t"
  169.                  "fld       fa1, (a0)\n\t"
  170.                  
  171.                  "fsd     fa1, 32(sp)\n\t"     // rad01が正常に読み込めてるかの確認用
  172.                  
  173.                  "fmul.d  fa0, fa1, fa0\n\t"
  174.  
  175.                  "fmv.x.d  a0, fa0\n\t"        // abiがlp64fなのでパラメーターを整数レジスタで渡す
  176.                  "call    cos01\n\t"
  177.                  "fmv.d.x  fa0, a0\n\t"        // abiがlp64fなので整数レジスタに戻り値が返ってくる
  178.  
  179.                  "fmul.d  fa0, fa0, fs2\n\t"
  180.                  "fadd.d  fa0, fa0, fs4\n\t"
  181.                  "fcvt.w.d  s8, fa0\n\t"
  182.  
  183.                  "lw       a0, 4(sp)\n\t"
  184.                  "mulw     a0, a0, a0\n\t"
  185.                  "fcvt.d.w  fa0, s4\n\t"
  186.                  "ld      a0, 8(sp)\n\t"
  187.                  "fld       fa1, (a0)\n\t"
  188.  
  189.                  "fsd     fa1, 40(sp)\n\t"     // rad01が正常に読み込めてるかの確認用
  190.                  
  191.                  "fmul.d  fa0, fa1, fa0\n\t"
  192.  
  193.                  "fmv.x.d  a0, fa0\n\t"        // abiがlp64fなのでパラメーターを整数レジスタで渡す
  194.                  "call    sin01\n\t"
  195.                  "fmv.d.x  fa0, a0\n\t"        // abiがlp64fなので整数レジスタに戻り値が返ってくる
  196.                
  197.                  "fmul.d  fa0, fa0, fs3\n\t"
  198.                  "fadd.d  fa0, fa0, fs5\n\t"
  199.                  "fcvt.w.d  s1, fa0\n\t"
  200.                
  201.                  "bne     s4, zero, jump02\n\t"
  202.  
  203.                  "move    s2, s8\n\t"
  204.                  "move    s3, s1\n\t"
  205.  
  206.     "jump02:\n\t"
  207.                  "move    a0, s8\n\t"
  208.                  "move    a1, s1\n\t"
  209.                  "move    a2, s2\n\t"
  210.                  "move    a3, s3\n\t"
  211.                  "move    a4, s5\n\t"
  212.                  "move    a5, s6\n\t"
  213.                  "move    a6, s7\n\t"
  214.                  "call    line\n\t"
  215.  
  216. /*
  217.                  "move    a0, s8\n\t"           // x1の値確認用
  218.                  "move    a1, s1\n\t"           // y1の値確認用
  219.                  "call    print_number_x_y\n\t"
  220.  
  221.                  "move    a0, s2\n\t"           // x2の値確認用
  222.                  "move    a1, s3\n\t"           // y2の値確認用
  223.                  "call    print_number_x_y\n\t"
  224.  
  225.                  "ld      a0, 32(sp)\n\t"       // 保存しておいたrad01の値確認用
  226.                  "ld      a1, 40(sp)\n\t"       // 保存しておいたrad01の値確認用
  227.                  // abiがlp64fなのでパラメーターを整数レジスタで渡す
  228.                  "call    print_number_x_y_double\n\t"
  229.  
  230.                  "fmv.x.d  a0, fs2\n\t"         // raの値確認用
  231.                  "fmv.x.d  a1, fs3\n\t"         // rbの値確認用
  232.                  // abiがlp64fなのでパラメーターを整数レジスタで渡す
  233.                  "call    print_number_x_y_double\n\t"
  234.  
  235.                  "fmv.x.d  a0, fs4\n\t"        // xcの値確認用
  236.                  "fmv.x.d  a1, fs5\n\t"        // ycの値確認用
  237.                  // abiがlp64fなのでパラメーターを整数レジスタで渡す
  238.                  "call    print_number_x_y_double\n\t"
  239. */
  240.  
  241.  
  242.                  "move    s2, s8\n\t"
  243.                  "move    s3, s1\n\t"
  244.  
  245.                  "li      a0, 10\n\t"
  246.                  "call    delay01\n\t"
  247.  
  248.                 "addiw    s4, s4, 1\n\t"
  249.                 "j       loop01\n\t"
  250.  
  251.     "jump01:\n\t"
  252.  
  253.                 "lw      %0,  0(sp)\n\t"        // 関数呼び出しで破壊されてしまうがインラインアセンブラの後でaを使う場合は値を戻さないとおかしくなる
  254.                 "lw      %1,  4(sp)\n\t"        // 関数呼び出しで破壊されてしまうがインラインアセンブラの後でbを使う場合は値を戻さないとおかしくなる
  255.                 "ld      %2,  8(sp)\n\t"        // 関数呼び出しで破壊されてしまうがインラインアセンブラの後でrad01を使う場合は値を戻さないとおかしくなる
  256.                 "ld      %3, 16(sp)\n\t"        // 関数呼び出しで破壊されてしまうがインラインアセンブラの後でwidth01を使う場合は値を戻さないとおかしくなる
  257.                 "ld      %4, 24(sp)\n\t"        // 関数呼び出しで破壊されてしまうがインラインアセンブラの後でheight01を使う場合は値を戻さないとおかしくなる
  258.  
  259.                 "addi    sp, sp, 48\n\t"
  260.  
  261.                 :
  262.                 :"r"(a), "r"(b), "r"(&rad01), "r"(&width01), "r"(&height01)
  263.                 :"x1", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x9", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "f10", "f11", "f12", "f18", "f19", "f20", "f21", "f22", "f23", "memory"
  264.     );
  265.  
  266.     // Serial.printf("rad01 = %.15f, width01 = %d, height01 = %d\r\n", rad01, width01, height01);
  267.  
  268.     return 0;
  269. }
  270.  
  271. void print_number_x_y(int x, int y) {
  272.     Serial.print("x = ");
  273.     Serial.printf("%d", x);
  274.     Serial.print("  ");
  275.     Serial.print("y = ");
  276.     Serial.printf("%d", y);
  277.     Serial.println();
  278. }
  279.  
  280. void print_number_x_y_double(double x, double y) {
  281.     Serial.print("x = ");
  282.     Serial.printf("%.15g", x);
  283.     Serial.print("  ");
  284.     Serial.print("y = ");
  285.     Serial.printf("%.15g", y);
  286.     Serial.println();
  287. }
  288.  
  289. void line(int x1, int y1, int x2, int y2, int colr, int colg, int colb) {
  290.     int color = colb | (colg << 5) | (colr << (5 + 6));
  291.     lcd.drawLine((int16_t)x1, (int16_t)y1, (int16_t)x2, (int16_t)y2, (uint16_t) color);
  292. }
  293.  
  294. double sin01(double a) {
  295.     return sin(a);
  296. }
  297.  
  298. double cos01(double a) {
  299.     return cos(a);
  300. }
  301.  
  302. int random01(int min, int max) {
  303.     return random(min, max);
  304. }
  305.  
  306. void delay01(int ms){
  307.     delay((unsigned long)ms);
  308. }
  309.  
  310. void lcd_clear01(void) {
  311.     lcd.fillRect(0, 0, 320, 240, COLOR_BLACK);
  312. }
Add Comment
Please, Sign In to add comment