Advertisement
Guest User

Untitled

a guest
Apr 28th, 2021
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 62.97 KB | None | 0 0
  1. /*
  2.  * RISCV emulator
  3.  *
  4.  * Copyright (c) 2016 Fabrice Bellard
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a copy
  7.  * of this software and associated documentation files (the "Software"), to deal
  8.  * in the Software without restriction, including without limitation the rights
  9.  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10.  * copies of the Software, and to permit persons to whom the Software is
  11.  * furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included in
  14.  * all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22.  * THE SOFTWARE.
  23.  */
  24. #if XLEN == 32
  25. #define uintx_t uint32_t
  26. #define intx_t int32_t
  27. #elif XLEN == 64
  28. #define uintx_t uint64_t
  29. #define intx_t int64_t
  30. #elif XLEN == 128
  31. #define uintx_t uint128_t
  32. #define intx_t int128_t
  33. #else
  34. #error unsupported XLEN
  35. #endif
  36.  
  37. static inline intx_t glue(div, XLEN)(intx_t a, intx_t b)
  38. {
  39.     if (b == 0) {
  40.         return -1;
  41.     } else if (a == ((intx_t)1 << (XLEN - 1)) && b == -1) {
  42.         return a;
  43.     } else {
  44.         return a / b;
  45.     }
  46. }
  47.  
  48. static inline uintx_t glue(divu, XLEN)(uintx_t a, uintx_t b)
  49. {
  50.     if (b == 0) {
  51.         return -1;
  52.     } else {
  53.         return a / b;
  54.     }
  55. }
  56.  
  57. static inline intx_t glue(rem, XLEN)(intx_t a, intx_t b)
  58. {
  59.     if (b == 0) {
  60.         return a;
  61.     } else if (a == ((intx_t)1 << (XLEN - 1)) && b == -1) {
  62.         return 0;
  63.     } else {
  64.         return a % b;
  65.     }
  66. }
  67.  
  68. static inline uintx_t glue(remu, XLEN)(uintx_t a, uintx_t b)
  69. {
  70.     if (b == 0) {
  71.         return a;
  72.     } else {
  73.         return a % b;
  74.     }
  75. }
  76.  
  77. #if XLEN == 32
  78.  
  79. static inline uint32_t mulh32(int32_t a, int32_t b)
  80. {
  81.     return ((int64_t)a * (int64_t)b) >> 32;
  82. }
  83.  
  84. static inline uint32_t mulhsu32(int32_t a, uint32_t b)
  85. {
  86.     return ((int64_t)a * (int64_t)b) >> 32;
  87. }
  88.  
  89. static inline uint32_t mulhu32(uint32_t a, uint32_t b)
  90. {
  91.     return ((int64_t)a * (int64_t)b) >> 32;
  92. }
  93.  
  94. #elif XLEN == 64 && defined(HAVE_INT128)
  95.  
  96. static inline uint64_t mulh64(int64_t a, int64_t b)
  97. {
  98.     return ((int128_t)a * (int128_t)b) >> 64;
  99. }
  100.  
  101. static inline uint64_t mulhsu64(int64_t a, uint64_t b)
  102. {
  103.     return ((int128_t)a * (int128_t)b) >> 64;
  104. }
  105.  
  106. static inline uint64_t mulhu64(uint64_t a, uint64_t b)
  107. {
  108.     return ((int128_t)a * (int128_t)b) >> 64;
  109. }
  110.  
  111. #else
  112.  
  113. #if XLEN == 64
  114. #define UHALF uint32_t
  115. #define UHALF_LEN 32
  116. #elif XLEN == 128
  117. #define UHALF uint64_t
  118. #define UHALF_LEN 64
  119. #else
  120. #error unsupported XLEN
  121. #endif
  122.  
  123. static uintx_t glue(mulhu, XLEN)(uintx_t a, uintx_t b)
  124. {
  125.     UHALF a0, a1, b0, b1, r2, r3;
  126.     uintx_t r00, r01, r10, r11, c;
  127.     a0 = a;
  128.     a1 = a >> UHALF_LEN;
  129.     b0 = b;
  130.     b1 = b >> UHALF_LEN;
  131.  
  132.     r00 = (uintx_t)a0 * (uintx_t)b0;
  133.     r01 = (uintx_t)a0 * (uintx_t)b1;
  134.     r10 = (uintx_t)a1 * (uintx_t)b0;
  135.     r11 = (uintx_t)a1 * (uintx_t)b1;
  136.    
  137.     //    r0 = r00;
  138.     c = (r00 >> UHALF_LEN) + (UHALF)r01 + (UHALF)r10;
  139.     //    r1 = c;
  140.     c = (c >> UHALF_LEN) + (r01 >> UHALF_LEN) + (r10 >> UHALF_LEN) + (UHALF)r11;
  141.     r2 = c;
  142.     r3 = (c >> UHALF_LEN) + (r11 >> UHALF_LEN);
  143.  
  144.     //    *plow = ((uintx_t)r1 << UHALF_LEN) | r0;
  145.     return ((uintx_t)r3 << UHALF_LEN) | r2;
  146. }
  147.  
  148. #undef UHALF
  149.  
  150. static inline uintx_t glue(mulh, XLEN)(intx_t a, intx_t b)
  151. {
  152.     uintx_t r1;
  153.     r1 = glue(mulhu, XLEN)(a, b);
  154.     if (a < 0)
  155.         r1 -= a;
  156.     if (b < 0)
  157.         r1 -= b;
  158.     return r1;
  159. }
  160.  
  161. static inline uintx_t glue(mulhsu, XLEN)(intx_t a, uintx_t b)
  162. {
  163.     uintx_t r1;
  164.     r1 = glue(mulhu, XLEN)(a, b);
  165.     if (a < 0)
  166.         r1 -= a;
  167.     return r1;
  168. }
  169.  
  170. #endif
  171.  
  172. #define DUP2(F, n) F(n) F(n+1)
  173. #define DUP4(F, n) DUP2(F, n) DUP2(F, n + 2)
  174. #define DUP8(F, n) DUP4(F, n) DUP4(F, n + 4)
  175. #define DUP16(F, n) DUP8(F, n) DUP8(F, n + 8)
  176. #define DUP32(F, n) DUP16(F, n) DUP16(F, n + 16)
  177.  
  178. #define C_QUADRANT(n) \
  179.     case n+(0 << 2): case n+(1 << 2): case n+(2 << 2): case n+(3 << 2): \
  180.     case n+(4 << 2): case n+(5 << 2): case n+(6 << 2): case n+(7 << 2): \
  181.     case n+(8 << 2): case n+(9 << 2): case n+(10 << 2): case n+(11 << 2): \
  182.     case n+(12 << 2): case n+(13 << 2): case n+(14 << 2): case n+(15 << 2): \
  183.     case n+(16 << 2): case n+(17 << 2): case n+(18 << 2): case n+(19 << 2): \
  184.     case n+(20 << 2): case n+(21 << 2): case n+(22 << 2): case n+(23 << 2): \
  185.     case n+(24 << 2): case n+(25 << 2): case n+(26 << 2): case n+(27 << 2): \
  186.     case n+(28 << 2): case n+(29 << 2): case n+(30 << 2): case n+(31 << 2):
  187.  
  188. #define GET_PC() (target_ulong)((uintptr_t)code_ptr + code_to_pc_addend)
  189. #define GET_INSN_COUNTER() (insn_counter_addend - s->n_cycles)
  190.  
  191. #define C_NEXT_INSN code_ptr += 2; break
  192. #define NEXT_INSN code_ptr += 4; break
  193. #define JUMP_INSN do {   \
  194.         code_ptr = NULL;           \
  195.         code_end = NULL;           \
  196.         code_to_pc_addend = s->pc; \
  197.         goto jump_insn;            \
  198.     } while (0)
  199.  
  200. static void no_inline glue(riscv_cpu_interp_x, XLEN)(RISCVCPUState *s,
  201.                                                    int n_cycles1)
  202. {
  203.     uint32_t opcode, insn, rd, rs1, rs2, funct3;
  204.     int32_t imm, cond, err;
  205.     target_ulong addr, val, val2;
  206. #ifndef USE_GLOBAL_VARIABLES
  207.     uint8_t *code_ptr, *code_end;
  208.     target_ulong code_to_pc_addend;
  209. #endif
  210.     uint64_t insn_counter_addend;
  211. #if FLEN > 0
  212.     uint32_t rs3;
  213.     int32_t rm;
  214. #endif
  215.  
  216.     if (n_cycles1 == 0)
  217.         return;
  218.     insn_counter_addend = s->insn_counter + n_cycles1;
  219.     s->n_cycles = n_cycles1;
  220.  
  221.     /* check pending interrupts */
  222.     if (unlikely((s->mip & s->mie) != 0)) {
  223.         if (raise_interrupt(s)) {
  224.             s->n_cycles--;
  225.             goto done_interp;
  226.         }
  227.     }
  228.  
  229.     s->pending_exception = -1;
  230.     /* Note: we assume NULL is represented as a zero number */
  231.     code_ptr = NULL;
  232.     code_end = NULL;
  233.     code_to_pc_addend = s->pc;
  234.    
  235.     /* we use a single execution loop to keep a simple control flow
  236.        for emscripten */
  237.     for(;;) {
  238.         if (unlikely(code_ptr >= code_end)) {
  239.             uint32_t tlb_idx;
  240.             uint16_t insn_high;
  241.             target_ulong addr;
  242.             uint8_t *ptr;
  243.            
  244.             s->pc = GET_PC();
  245.             /* we test n_cycles only between blocks so that timer
  246.                interrupts only happen between the blocks. It is
  247.                important to reduce the translated code size. */
  248.             if (unlikely(s->n_cycles <= 0))
  249.                 goto the_end;
  250.  
  251.             /* check pending interrupts */
  252.             if (unlikely((s->mip & s->mie) != 0)) {
  253.                 if (raise_interrupt(s)) {
  254.                     s->n_cycles--;
  255.                     goto the_end;
  256.                 }
  257.             }
  258.    
  259.             addr = s->pc;
  260.             tlb_idx = (addr >> PG_SHIFT) & (TLB_SIZE - 1);
  261.             if (likely(s->tlb_code[tlb_idx].vaddr == (addr & ~PG_MASK))) {
  262.                 /* TLB match */
  263.                 ptr = (uint8_t *)(s->tlb_code[tlb_idx].mem_addend +
  264.                                   (uintptr_t)addr);
  265.             } else {
  266.                 if (unlikely(target_read_insn_slow(s, &ptr, addr)))
  267.                     goto mmu_exception;
  268.             }
  269.             code_ptr = ptr;
  270.             code_end = ptr + (PG_MASK - 1 - (addr & PG_MASK));
  271.             code_to_pc_addend = addr - (uintptr_t)code_ptr;
  272.             if (unlikely(code_ptr >= code_end)) {
  273.                 /* instruction is potentially half way between two
  274.                    pages ? */
  275.                 insn = *(uint16_t *)code_ptr;
  276.                 if ((insn & 3) == 3) {
  277.                     /* instruction is half way between two pages */
  278.                     if (unlikely(target_read_insn_u16(s, &insn_high, addr + 2)))
  279.                         goto mmu_exception;
  280.                     insn |= insn_high << 16;
  281.                 }
  282.             } else {
  283.                 insn = get_insn32(code_ptr);
  284.             }
  285.         } else {
  286.             /* fast path */
  287.             insn = get_insn32(code_ptr);
  288.         }
  289.         s->n_cycles--;
  290. #if 0
  291.         if (1) {
  292. #ifdef CONFIG_LOGFILE
  293.             log_printf("pc=0x"); fprint_target_ulong(log_file, GET_PC()); log_printf(" insn=%08x\n", insn);
  294.             fflush(log_file);
  295. #else
  296.             printf("pc=0x"); print_target_ulong(GET_PC()); printf(" insn=%08x\n", insn);
  297.             //            dump_regs(s);
  298. #endif
  299.         }
  300. #endif
  301.         opcode = insn & 0x7f;
  302.         rd = (insn >> 7) & 0x1f;
  303.         rs1 = (insn >> 15) & 0x1f;
  304.         rs2 = (insn >> 20) & 0x1f;
  305.         switch(opcode) {
  306. #ifdef CONFIG_EXT_C
  307.         C_QUADRANT(0)
  308.             funct3 = (insn >> 13) & 7;
  309.             rd = ((insn >> 2) & 7) | 8;
  310.             switch(funct3) {
  311.             case 0: /* c.addi4spn */
  312.                 imm = get_field1(insn, 11, 4, 5) |
  313.                     get_field1(insn, 7, 6, 9) |
  314.                     get_field1(insn, 6, 2, 2) |
  315.                     get_field1(insn, 5, 3, 3);
  316.                 if (imm == 0)
  317.                     goto illegal_insn;
  318.                 s->reg[rd] = (intx_t)(s->reg[2] + imm);
  319.                 break;
  320. #if XLEN >= 128
  321.             case 1: /* c.lq */
  322.                 imm = get_field1(insn, 11, 4, 5) |
  323.                     get_field1(insn, 10, 8, 8) |
  324.                     get_field1(insn, 5, 6, 7);
  325.                 rs1 = ((insn >> 7) & 7) | 8;
  326.                 addr = (intx_t)(s->reg[rs1] + imm);
  327.                 if (target_read_u128(s, &val, addr))
  328.                     goto mmu_exception;
  329.                 s->reg[rd] = val;
  330.                 break;
  331. #elif FLEN >= 64
  332.             case 1: /* c.fld */
  333.                 {
  334.                     uint64_t rval;
  335.                     if (s->fs == 0)
  336.                         goto illegal_insn;
  337.                     imm = get_field1(insn, 10, 3, 5) |
  338.                         get_field1(insn, 5, 6, 7);
  339.                     rs1 = ((insn >> 7) & 7) | 8;
  340.                     addr = (intx_t)(s->reg[rs1] + imm);
  341.                     if (target_read_u64(s, &rval, addr))
  342.                         goto mmu_exception;
  343.                     s->fp_reg[rd] = rval | F64_HIGH;
  344.                     s->fs = 3;
  345.                 }
  346.                 break;
  347. #endif
  348.             case 2: /* c.lw */
  349.                 {
  350.                     uint32_t rval;
  351.                     imm = get_field1(insn, 10, 3, 5) |
  352.                         get_field1(insn, 6, 2, 2) |
  353.                         get_field1(insn, 5, 6, 6);
  354.                     rs1 = ((insn >> 7) & 7) | 8;
  355.                     addr = (intx_t)(s->reg[rs1] + imm);
  356.                     if (target_read_u32(s, &rval, addr))
  357.                         goto mmu_exception;
  358.                     s->reg[rd] = (int32_t)rval;
  359.                 }
  360.                 break;
  361. #if XLEN >= 64
  362.             case 3: /* c.ld */
  363.                 {
  364.                     uint64_t rval;
  365.                     imm = get_field1(insn, 10, 3, 5) |
  366.                         get_field1(insn, 5, 6, 7);
  367.                     rs1 = ((insn >> 7) & 7) | 8;
  368.                     addr = (intx_t)(s->reg[rs1] + imm);
  369.                     if (target_read_u64(s, &rval, addr))
  370.                         goto mmu_exception;
  371.                     s->reg[rd] = (int64_t)rval;
  372.                 }
  373.                 break;
  374. #elif FLEN >= 32
  375.             case 3: /* c.flw */
  376.                 {
  377.                     uint32_t rval;
  378.                     if (s->fs == 0)
  379.                         goto illegal_insn;
  380.                     imm = get_field1(insn, 10, 3, 5) |
  381.                         get_field1(insn, 6, 2, 2) |
  382.                         get_field1(insn, 5, 6, 6);
  383.                     rs1 = ((insn >> 7) & 7) | 8;
  384.                     addr = (intx_t)(s->reg[rs1] + imm);
  385.                     if (target_read_u32(s, &rval, addr))
  386.                         goto mmu_exception;
  387.                     s->fp_reg[rd] = rval | F32_HIGH;
  388.                     s->fs = 3;
  389.                 }
  390.                 break;
  391. #endif
  392. #if XLEN >= 128
  393.             case 5: /* c.sq */
  394.                 imm = get_field1(insn, 11, 4, 5) |
  395.                     get_field1(insn, 10, 8, 8) |
  396.                     get_field1(insn, 5, 6, 7);
  397.                 rs1 = ((insn >> 7) & 7) | 8;
  398.                 addr = (intx_t)(s->reg[rs1] + imm);
  399.                 val = s->reg[rd];
  400.                 if (target_write_u128(s, addr, val))
  401.                     goto mmu_exception;
  402.                 break;
  403. #elif FLEN >= 64
  404.             case 5: /* c.fsd */
  405.                 if (s->fs == 0)
  406.                     goto illegal_insn;
  407.                 imm = get_field1(insn, 10, 3, 5) |
  408.                     get_field1(insn, 5, 6, 7);
  409.                 rs1 = ((insn >> 7) & 7) | 8;
  410.                 addr = (intx_t)(s->reg[rs1] + imm);
  411.                 if (target_write_u64(s, addr, s->fp_reg[rd]))
  412.                     goto mmu_exception;
  413.                 break;
  414. #endif
  415.             case 6: /* c.sw */
  416.                 imm = get_field1(insn, 10, 3, 5) |
  417.                     get_field1(insn, 6, 2, 2) |
  418.                     get_field1(insn, 5, 6, 6);
  419.                 rs1 = ((insn >> 7) & 7) | 8;
  420.                 addr = (intx_t)(s->reg[rs1] + imm);
  421.                 val = s->reg[rd];
  422.                 if (target_write_u32(s, addr, val))
  423.                     goto mmu_exception;
  424.                 break;
  425. #if XLEN >= 64
  426.             case 7: /* c.sd */
  427.                 imm = get_field1(insn, 10, 3, 5) |
  428.                     get_field1(insn, 5, 6, 7);
  429.                 rs1 = ((insn >> 7) & 7) | 8;
  430.                 addr = (intx_t)(s->reg[rs1] + imm);
  431.                 val = s->reg[rd];
  432.                 if (target_write_u64(s, addr, val))
  433.                     goto mmu_exception;
  434.                 break;
  435. #elif FLEN >= 32
  436.             case 7: /* c.fsw */
  437.                 if (s->fs == 0)
  438.                     goto illegal_insn;
  439.                 imm = get_field1(insn, 10, 3, 5) |
  440.                     get_field1(insn, 6, 2, 2) |
  441.                     get_field1(insn, 5, 6, 6);
  442.                 rs1 = ((insn >> 7) & 7) | 8;
  443.                 addr = (intx_t)(s->reg[rs1] + imm);
  444.                 if (target_write_u32(s, addr, s->fp_reg[rd]))
  445.                     goto mmu_exception;
  446.                 break;
  447. #endif
  448.             default:
  449.                 goto illegal_insn;
  450.             }
  451.             C_NEXT_INSN;
  452.         C_QUADRANT(1)
  453.             funct3 = (insn >> 13) & 7;
  454.             switch(funct3) {
  455.             case 0: /* c.addi/c.nop */
  456.                 if (rd != 0) {
  457.                     imm = sext(get_field1(insn, 12, 5, 5) |
  458.                                get_field1(insn, 2, 0, 4), 6);
  459.                     s->reg[rd] = (intx_t)(s->reg[rd] + imm);
  460.                 }
  461.                 break;
  462. #if XLEN == 32
  463.             case 1: /* c.jal */
  464.                 imm = sext(get_field1(insn, 12, 11, 11) |
  465.                            get_field1(insn, 11, 4, 4) |
  466.                            get_field1(insn, 9, 8, 9) |
  467.                            get_field1(insn, 8, 10, 10) |
  468.                            get_field1(insn, 7, 6, 6) |
  469.                            get_field1(insn, 6, 7, 7) |
  470.                            get_field1(insn, 3, 1, 3) |
  471.                            get_field1(insn, 2, 5, 5), 12);
  472.                 s->reg[1] = GET_PC() + 2;
  473.                 s->pc = (intx_t)(GET_PC() + imm);
  474.                 JUMP_INSN;
  475. #else
  476.             case 1: /* c.addiw */
  477.                 if (rd != 0) {
  478.                     imm = sext(get_field1(insn, 12, 5, 5) |
  479.                                get_field1(insn, 2, 0, 4), 6);
  480.                     s->reg[rd] = (int32_t)(s->reg[rd] + imm);
  481.                 }
  482.                 break;
  483. #endif
  484.             case 2: /* c.li */
  485.                 if (rd != 0) {
  486.                     imm = sext(get_field1(insn, 12, 5, 5) |
  487.                                get_field1(insn, 2, 0, 4), 6);
  488.                     s->reg[rd] = imm;
  489.                 }
  490.                 break;
  491.             case 3:
  492.                 if (rd == 2) {
  493.                     /* c.addi16sp */
  494.                     imm = sext(get_field1(insn, 12, 9, 9) |
  495.                                get_field1(insn, 6, 4, 4) |
  496.                                get_field1(insn, 5, 6, 6) |
  497.                                get_field1(insn, 3, 7, 8) |
  498.                                get_field1(insn, 2, 5, 5), 10);
  499.                     if (imm == 0)
  500.                         goto illegal_insn;
  501.                     s->reg[2] = (intx_t)(s->reg[2] + imm);
  502.                 } else if (rd != 0) {
  503.                     /* c.lui */
  504.                     imm = sext(get_field1(insn, 12, 17, 17) |
  505.                                get_field1(insn, 2, 12, 16), 18);
  506.                     s->reg[rd] = imm;
  507.                 }
  508.                 break;
  509.             case 4:
  510.                 funct3 = (insn >> 10) & 3;
  511.                 rd = ((insn >> 7) & 7) | 8;
  512.                 switch(funct3) {
  513.                 case 0: /* c.srli */
  514.                 case 1: /* c.srai */
  515.                     imm = get_field1(insn, 12, 5, 5) |
  516.                         get_field1(insn, 2, 0, 4);
  517. #if XLEN == 32
  518.                     if (imm & 0x20)
  519.                         goto illegal_insn;
  520. #elif XLEN == 128
  521.                     if (imm == 0)
  522.                         imm = 64;
  523.                     else if (imm >= 32)
  524.                         imm = 128 - imm;
  525. #endif
  526.                     if (funct3 == 0)
  527.                         s->reg[rd] = (intx_t)((uintx_t)s->reg[rd] >> imm);
  528.                     else
  529.                         s->reg[rd] = (intx_t)s->reg[rd] >> imm;
  530.                    
  531.                     break;
  532.                 case 2: /* c.andi */
  533.                     imm = sext(get_field1(insn, 12, 5, 5) |
  534.                                get_field1(insn, 2, 0, 4), 6);
  535.                     s->reg[rd] &= imm;
  536.                     break;
  537.                 case 3:
  538.                     rs2 = ((insn >> 2) & 7) | 8;
  539.                     funct3 = ((insn >> 5) & 3) | ((insn >> (12 - 2)) & 4);
  540.                     switch(funct3) {
  541.                     case 0: /* c.sub */
  542.                         s->reg[rd] = (intx_t)(s->reg[rd] - s->reg[rs2]);
  543.                         break;
  544.                     case 1: /* c.xor */
  545.                         s->reg[rd] = s->reg[rd] ^ s->reg[rs2];
  546.                         break;
  547.                     case 2: /* c.or */
  548.                         s->reg[rd] = s->reg[rd] | s->reg[rs2];
  549.                         break;
  550.                     case 3: /* c.and */
  551.                         s->reg[rd] = s->reg[rd] & s->reg[rs2];
  552.                         break;
  553. #if XLEN >= 64
  554.                     case 4: /* c.subw */
  555.                         s->reg[rd] = (int32_t)(s->reg[rd] - s->reg[rs2]);
  556.                         break;
  557.                     case 5: /* c.addw */
  558.                         s->reg[rd] = (int32_t)(s->reg[rd] + s->reg[rs2]);
  559.                         break;
  560. #endif
  561.                     default:
  562.                         goto illegal_insn;
  563.                     }
  564.                     break;
  565.                 }
  566.                 break;
  567.             case 5: /* c.j */
  568.                 imm = sext(get_field1(insn, 12, 11, 11) |
  569.                            get_field1(insn, 11, 4, 4) |
  570.                            get_field1(insn, 9, 8, 9) |
  571.                            get_field1(insn, 8, 10, 10) |
  572.                            get_field1(insn, 7, 6, 6) |
  573.                            get_field1(insn, 6, 7, 7) |
  574.                            get_field1(insn, 3, 1, 3) |
  575.                            get_field1(insn, 2, 5, 5), 12);
  576.                 s->pc = (intx_t)(GET_PC() + imm);
  577.                 JUMP_INSN;
  578.             case 6: /* c.beqz */
  579.                 rs1 = ((insn >> 7) & 7) | 8;
  580.                 imm = sext(get_field1(insn, 12, 8, 8) |
  581.                            get_field1(insn, 10, 3, 4) |
  582.                            get_field1(insn, 5, 6, 7) |
  583.                            get_field1(insn, 3, 1, 2) |
  584.                            get_field1(insn, 2, 5, 5), 9);
  585.                 if (s->reg[rs1] == 0) {
  586.                     s->pc = (intx_t)(GET_PC() + imm);
  587.                     JUMP_INSN;
  588.                 }
  589.                 break;
  590.             case 7: /* c.bnez */
  591.                 rs1 = ((insn >> 7) & 7) | 8;
  592.                 imm = sext(get_field1(insn, 12, 8, 8) |
  593.                            get_field1(insn, 10, 3, 4) |
  594.                            get_field1(insn, 5, 6, 7) |
  595.                            get_field1(insn, 3, 1, 2) |
  596.                            get_field1(insn, 2, 5, 5), 9);
  597.                 if (s->reg[rs1] != 0) {
  598.                     s->pc = (intx_t)(GET_PC() + imm);
  599.                     JUMP_INSN;
  600.                 }
  601.                 break;
  602.             default:
  603.                 goto illegal_insn;
  604.             }
  605.             C_NEXT_INSN;
  606.         C_QUADRANT(2)
  607.             funct3 = (insn >> 13) & 7;
  608.             rs2 = (insn >> 2) & 0x1f;
  609.             switch(funct3) {
  610.             case 0: /* c.slli */
  611.                 imm = get_field1(insn, 12, 5, 5) | rs2;
  612. #if XLEN == 32
  613.                 if (imm & 0x20)
  614.                     goto illegal_insn;
  615. #elif XLEN == 128
  616.                 if (imm == 0)
  617.                     imm = 64;
  618. #endif
  619.                 if (rd != 0)
  620.                     s->reg[rd] = (intx_t)(s->reg[rd] << imm);
  621.                 break;
  622. #if XLEN == 128
  623.             case 1: /* c.lqsp */
  624.                 imm = get_field1(insn, 12, 5, 5) |
  625.                     (rs2 & (1 << 4)) |
  626.                     get_field1(insn, 2, 6, 9);
  627.                 addr = (intx_t)(s->reg[2] + imm);
  628.                 if (target_read_u128(s, &val, addr))
  629.                     goto mmu_exception;
  630.                 if (rd != 0)
  631.                     s->reg[rd] = val;
  632.                 break;
  633. #elif FLEN >= 64
  634.             case 1: /* c.fldsp */
  635.                 {
  636.                     uint64_t rval;
  637.                     if (s->fs == 0)
  638.                         goto illegal_insn;
  639.                     imm = get_field1(insn, 12, 5, 5) |
  640.                         (rs2 & (3 << 3)) |
  641.                         get_field1(insn, 2, 6, 8);
  642.                     addr = (intx_t)(s->reg[2] + imm);
  643.                     if (target_read_u64(s, &rval, addr))
  644.                         goto mmu_exception;
  645.                     s->fp_reg[rd] = rval | F64_HIGH;
  646.                     s->fs = 3;
  647.                 }
  648.                 break;
  649. #endif
  650.             case 2: /* c.lwsp */
  651.                 {
  652.                     uint32_t rval;
  653.                     imm = get_field1(insn, 12, 5, 5) |
  654.                         (rs2 & (7 << 2)) |
  655.                         get_field1(insn, 2, 6, 7);
  656.                     addr = (intx_t)(s->reg[2] + imm);
  657.                     if (target_read_u32(s, &rval, addr))
  658.                         goto mmu_exception;
  659.                     if (rd != 0)
  660.                         s->reg[rd] = (int32_t)rval;
  661.                 }
  662.                 break;
  663. #if XLEN >= 64
  664.             case 3: /* c.ldsp */
  665.                 {
  666.                     uint64_t rval;
  667.                     imm = get_field1(insn, 12, 5, 5) |
  668.                         (rs2 & (3 << 3)) |
  669.                         get_field1(insn, 2, 6, 8);
  670.                     addr = (intx_t)(s->reg[2] + imm);
  671.                     if (target_read_u64(s, &rval, addr))
  672.                         goto mmu_exception;
  673.                     if (rd != 0)
  674.                         s->reg[rd] = (int64_t)rval;
  675.                 }
  676.                 break;
  677. #elif FLEN >= 32
  678.             case 3: /* c.flwsp */
  679.                 {
  680.                     uint32_t rval;
  681.                     if (s->fs == 0)
  682.                         goto illegal_insn;
  683.                     imm = get_field1(insn, 12, 5, 5) |
  684.                         (rs2 & (7 << 2)) |
  685.                         get_field1(insn, 2, 6, 7);
  686.                     addr = (intx_t)(s->reg[2] + imm);
  687.                     if (target_read_u32(s, &rval, addr))
  688.                         goto mmu_exception;
  689.                     s->fp_reg[rd] = rval | F32_HIGH;
  690.                     s->fs = 3;
  691.                 }
  692.                 break;
  693. #endif
  694.             case 4:
  695.                 if (((insn >> 12) & 1) == 0) {
  696.                     if (rs2 == 0) {
  697.                         /* c.jr */
  698.                         if (rd == 0)
  699.                             goto illegal_insn;
  700.                         s->pc = s->reg[rd] & ~1;
  701.                         JUMP_INSN;
  702.                     } else {
  703.                         /* c.mv */
  704.                         if (rd != 0)
  705.                             s->reg[rd] = s->reg[rs2];
  706.                     }
  707.                 } else {
  708.                     if (rs2 == 0) {
  709.                         if (rd == 0) {
  710.                             /* c.ebreak */
  711.                             s->pending_exception = CAUSE_BREAKPOINT;
  712.                             goto exception;
  713.                         } else {
  714.                             /* c.jalr */
  715.                             val = GET_PC() + 2;
  716.                             s->pc = s->reg[rd] & ~1;
  717.                             s->reg[1] = val;
  718.                             JUMP_INSN;
  719.                         }
  720.                     } else {
  721.                         if (rd != 0) {
  722.                             s->reg[rd] = (intx_t)(s->reg[rd] + s->reg[rs2]);
  723.                         }
  724.                     }
  725.                 }
  726.                 break;
  727. #if XLEN == 128
  728.             case 5: /* c.sqsp */
  729.                 imm = get_field1(insn, 10, 3, 5) |
  730.                     get_field1(insn, 7, 6, 8);
  731.                 addr = (intx_t)(s->reg[2] + imm);
  732.                 if (target_write_u128(s, addr, s->reg[rs2]))
  733.                     goto mmu_exception;
  734.                 break;
  735. #elif FLEN >= 64
  736.             case 5: /* c.fsdsp */
  737.                 if (s->fs == 0)
  738.                     goto illegal_insn;
  739.                 imm = get_field1(insn, 10, 3, 5) |
  740.                     get_field1(insn, 7, 6, 8);
  741.                 addr = (intx_t)(s->reg[2] + imm);
  742.                 if (target_write_u64(s, addr, s->fp_reg[rs2]))
  743.                     goto mmu_exception;
  744.                 break;
  745. #endif
  746.             case 6: /* c.swsp */
  747.                 imm = get_field1(insn, 9, 2, 5) |
  748.                     get_field1(insn, 7, 6, 7);
  749.                 addr = (intx_t)(s->reg[2] + imm);
  750.                 if (target_write_u32(s, addr, s->reg[rs2]))
  751.                     goto mmu_exception;
  752.                 break;
  753. #if XLEN >= 64
  754.             case 7: /* c.sdsp */
  755.                 imm = get_field1(insn, 10, 3, 5) |
  756.                     get_field1(insn, 7, 6, 8);
  757.                 addr = (intx_t)(s->reg[2] + imm);
  758.                 if (target_write_u64(s, addr, s->reg[rs2]))
  759.                     goto mmu_exception;
  760.                 break;
  761. #elif FLEN >= 32
  762.             case 7: /* c.swsp */
  763.                 if (s->fs == 0)
  764.                     goto illegal_insn;
  765.                 imm = get_field1(insn, 9, 2, 5) |
  766.                     get_field1(insn, 7, 6, 7);
  767.                 addr = (intx_t)(s->reg[2] + imm);
  768.                 if (target_write_u32(s, addr, s->fp_reg[rs2]))
  769.                     goto mmu_exception;
  770.                 break;
  771. #endif
  772.             default:
  773.                 goto illegal_insn;
  774.             }
  775.             C_NEXT_INSN;
  776. #endif /* CONFIG_EXT_C */
  777.  
  778.         case 0x37: /* lui */
  779.             if (rd != 0)
  780.                 s->reg[rd] = (int32_t)(insn & 0xfffff000);
  781.             NEXT_INSN;
  782.         case 0x17: /* auipc */
  783.             if (rd != 0)
  784.                 s->reg[rd] = (intx_t)(GET_PC() + (int32_t)(insn & 0xfffff000));
  785.             NEXT_INSN;
  786.         case 0x6f: /* jal */
  787.             imm = ((insn >> (31 - 20)) & (1 << 20)) |
  788.                 ((insn >> (21 - 1)) & 0x7fe) |
  789.                 ((insn >> (20 - 11)) & (1 << 11)) |
  790.                 (insn & 0xff000);
  791.             imm = (imm << 11) >> 11;
  792.             if (rd != 0)
  793.                 s->reg[rd] = GET_PC() + 4;
  794.             s->pc = (intx_t)(GET_PC() + imm);
  795.             JUMP_INSN;
  796.         case 0x67: /* jalr */
  797.             imm = (int32_t)insn >> 20;
  798.             val = GET_PC() + 4;
  799.             s->pc = (intx_t)(s->reg[rs1] + imm) & ~1;
  800.             if (rd != 0)
  801.                 s->reg[rd] = val;
  802.             JUMP_INSN;
  803.         case 0x63:
  804.             funct3 = (insn >> 12) & 7;
  805.             switch(funct3 >> 1) {
  806.             case 0: /* beq/bne */
  807.                 cond = (s->reg[rs1] == s->reg[rs2]);
  808.                 break;
  809.             case 2: /* blt/bge */
  810.                 cond = ((target_long)s->reg[rs1] < (target_long)s->reg[rs2]);
  811.                 break;
  812.             case 3: /* bltu/bgeu */
  813.                 cond = (s->reg[rs1] < s->reg[rs2]);
  814.                 break;
  815.             default:
  816.                 goto illegal_insn;
  817.             }
  818.             cond ^= (funct3 & 1);
  819.             if (cond) {
  820.                 imm = ((insn >> (31 - 12)) & (1 << 12)) |
  821.                     ((insn >> (25 - 5)) & 0x7e0) |
  822.                     ((insn >> (8 - 1)) & 0x1e) |
  823.                     ((insn << (11 - 7)) & (1 << 11));
  824.                 imm = (imm << 19) >> 19;
  825.                 s->pc = (intx_t)(GET_PC() + imm);
  826.                 JUMP_INSN;
  827.             }
  828.             NEXT_INSN;
  829.         case 0x03: /* load */
  830.             funct3 = (insn >> 12) & 7;
  831.             imm = (int32_t)insn >> 20;
  832.             addr = s->reg[rs1] + imm;
  833.             switch(funct3) {
  834.             case 0: /* lb */
  835.                 {
  836.                     uint8_t rval;
  837.                     if (target_read_u8(s, &rval, addr))
  838.                         goto mmu_exception;
  839.                     val = (int8_t)rval;
  840.                 }
  841.                 break;
  842.             case 1: /* lh */
  843.                 {
  844.                     uint16_t rval;
  845.                     if (target_read_u16(s, &rval, addr))
  846.                         goto mmu_exception;
  847.                     val = (int16_t)rval;
  848.                 }
  849.                 break;
  850.             case 2: /* lw */
  851.                 {
  852.                     uint32_t rval;
  853.                     if (target_read_u32(s, &rval, addr))
  854.                         goto mmu_exception;
  855.                     val = (int32_t)rval;
  856.                 }
  857.                 break;
  858.             case 4: /* lbu */
  859.                 {
  860.                     uint8_t rval;
  861.                     if (target_read_u8(s, &rval, addr))
  862.                         goto mmu_exception;
  863.                     val = rval;
  864.                 }
  865.                 break;
  866.             case 5: /* lhu */
  867.                 {
  868.                     uint16_t rval;
  869.                     if (target_read_u16(s, &rval, addr))
  870.                         goto mmu_exception;
  871.                     val = rval;
  872.                 }
  873.                 break;
  874. #if XLEN >= 64
  875.             case 3: /* ld */
  876.                 {
  877.                     uint64_t rval;
  878.                     if (target_read_u64(s, &rval, addr))
  879.                         goto mmu_exception;
  880.                     val = (int64_t)rval;
  881.                 }
  882.                 break;
  883.             case 6: /* lwu */
  884.                 {
  885.                     uint32_t rval;
  886.                     if (target_read_u32(s, &rval, addr))
  887.                         goto mmu_exception;
  888.                     val = rval;
  889.                 }
  890.                 break;
  891. #endif
  892. #if XLEN >= 128
  893.             case 7: /* ldu */
  894.                 {
  895.                     uint64_t rval;
  896.                     if (target_read_u64(s, &rval, addr))
  897.                         goto mmu_exception;
  898.                     val = rval;
  899.                 }
  900.                 break;
  901. #endif
  902.             default:
  903.                 goto illegal_insn;
  904.             }
  905.             if (rd != 0)
  906.                 s->reg[rd] = val;
  907.             NEXT_INSN;
  908.         case 0x23: /* store */
  909.             funct3 = (insn >> 12) & 7;
  910.             imm = rd | ((insn >> (25 - 5)) & 0xfe0);
  911.             imm = (imm << 20) >> 20;
  912.             addr = s->reg[rs1] + imm;
  913.             val = s->reg[rs2];
  914.             switch(funct3) {
  915.             case 0: /* sb */
  916.                 if (target_write_u8(s, addr, val))
  917.                     goto mmu_exception;
  918.                 break;
  919.             case 1: /* sh */
  920.                 if (target_write_u16(s, addr, val))
  921.                     goto mmu_exception;
  922.                 break;
  923.             case 2: /* sw */
  924.                 if (target_write_u32(s, addr, val))
  925.                     goto mmu_exception;
  926.                 break;
  927. #if XLEN >= 64
  928.             case 3: /* sd */
  929.                 if (target_write_u64(s, addr, val))
  930.                     goto mmu_exception;
  931.                 break;
  932. #endif
  933. #if XLEN >= 128
  934.             case 4: /* sq */
  935.                 if (target_write_u128(s, addr, val))
  936.                     goto mmu_exception;
  937.                 break;
  938. #endif
  939.             default:
  940.                 goto illegal_insn;
  941.             }
  942.             NEXT_INSN;
  943.         case 0x13:
  944.             funct3 = (insn >> 12) & 7;
  945.             imm = (int32_t)insn >> 20;
  946.             switch(funct3) {
  947.             case 0: /* addi */
  948.                 val = (intx_t)(s->reg[rs1] + imm);
  949.                 break;
  950.             case 1: /* slli */
  951.                 if ((imm & ~(XLEN - 1)) != 0)
  952.                     goto illegal_insn;
  953.                 val = (intx_t)(s->reg[rs1] << (imm & (XLEN - 1)));
  954.                 break;
  955.             case 2: /* slti */
  956.                 val = (target_long)s->reg[rs1] < (target_long)imm;
  957.                 break;
  958.             case 3: /* sltiu */
  959.                 val = s->reg[rs1] < (target_ulong)imm;
  960.                 break;
  961.             case 4: /* xori */
  962.                 val = s->reg[rs1] ^ imm;
  963.                 break;
  964.             case 5: /* srli/srai */
  965.                 if ((imm & ~((XLEN - 1) | 0x400)) != 0)
  966.                     goto illegal_insn;
  967.                 if (imm & 0x400)
  968.                     val = (intx_t)s->reg[rs1] >> (imm & (XLEN - 1));
  969.                 else
  970.                     val = (intx_t)((uintx_t)s->reg[rs1] >> (imm & (XLEN - 1)));
  971.                 break;
  972.             case 6: /* ori */
  973.                 val = s->reg[rs1] | imm;
  974.                 break;
  975.             default:
  976.             case 7: /* andi */
  977.                 val = s->reg[rs1] & imm;
  978.                 break;
  979.             }
  980.             if (rd != 0)
  981.                 s->reg[rd] = val;
  982.             NEXT_INSN;
  983. #if XLEN >= 64
  984.         case 0x1b:/* OP-IMM-32 */
  985.             funct3 = (insn >> 12) & 7;
  986.             imm = (int32_t)insn >> 20;
  987.             val = s->reg[rs1];
  988.             switch(funct3) {
  989.             case 0: /* addiw */
  990.                 val = (int32_t)(val + imm);
  991.                 break;
  992.             case 1: /* slliw */
  993.                 if ((imm & ~31) != 0)
  994.                     goto illegal_insn;
  995.                 val = (int32_t)(val << (imm & 31));
  996.                 break;
  997.             case 5: /* srliw/sraiw */
  998.                 if ((imm & ~(31 | 0x400)) != 0)
  999.                     goto illegal_insn;
  1000.                 if (imm & 0x400)
  1001.                     val = (int32_t)val >> (imm & 31);
  1002.                 else
  1003.                     val = (int32_t)((uint32_t)val >> (imm & 31));
  1004.                 break;
  1005.             default:
  1006.                 goto illegal_insn;
  1007.             }
  1008.             if (rd != 0)
  1009.                 s->reg[rd] = val;
  1010.             NEXT_INSN;
  1011. #endif
  1012. #if XLEN >= 128
  1013.         case 0x5b: /* OP-IMM-64 */
  1014.             funct3 = (insn >> 12) & 7;
  1015.             imm = (int32_t)insn >> 20;
  1016.             val = s->reg[rs1];
  1017.             switch(funct3) {
  1018.             case 0: /* addid */
  1019.                 val = (int64_t)(val + imm);
  1020.                 break;
  1021.             case 1: /* sllid */
  1022.                 if ((imm & ~63) != 0)
  1023.                     goto illegal_insn;
  1024.                 val = (int64_t)(val << (imm & 63));
  1025.                 break;
  1026.             case 5: /* srlid/sraid */
  1027.                 if ((imm & ~(63 | 0x400)) != 0)
  1028.                     goto illegal_insn;
  1029.                 if (imm & 0x400)
  1030.                     val = (int64_t)val >> (imm & 63);
  1031.                 else
  1032.                     val = (int64_t)((uint64_t)val >> (imm & 63));
  1033.                 break;
  1034.             default:
  1035.                 goto illegal_insn;
  1036.             }
  1037.             if (rd != 0)
  1038.                 s->reg[rd] = val;
  1039.             NEXT_INSN;
  1040. #endif
  1041.         case 0x33:
  1042.             imm = insn >> 25;
  1043.             val = s->reg[rs1];
  1044.             val2 = s->reg[rs2];
  1045.             if (imm == 1) {
  1046.                 funct3 = (insn >> 12) & 7;
  1047.                 switch(funct3) {
  1048.                 case 0: /* mul */
  1049.                     val = (intx_t)((intx_t)val * (intx_t)val2);
  1050.                     break;
  1051.                 case 1: /* mulh */
  1052.                     val = (intx_t)glue(mulh, XLEN)(val, val2);
  1053.                     break;
  1054.                 case 2:/* mulhsu */
  1055.                     val = (intx_t)glue(mulhsu, XLEN)(val, val2);
  1056.                     break;
  1057.                 case 3:/* mulhu */
  1058.                     val = (intx_t)glue(mulhu, XLEN)(val, val2);
  1059.                     break;
  1060.                 case 4:/* div */
  1061.                     val = glue(div, XLEN)(val, val2);
  1062.                     break;
  1063.                 case 5:/* divu */
  1064.                     val = (intx_t)glue(divu, XLEN)(val, val2);
  1065.                     break;
  1066.                 case 6:/* rem */
  1067.                     val = glue(rem, XLEN)(val, val2);
  1068.                     break;
  1069.                 case 7:/* remu */
  1070.                     val = (intx_t)glue(remu, XLEN)(val, val2);
  1071.                     break;
  1072.                 default:
  1073.                     goto illegal_insn;
  1074.                 }
  1075.             } else {
  1076.                 if (imm & ~0x20)
  1077.                     goto illegal_insn;
  1078.                 funct3 = ((insn >> 12) & 7) | ((insn >> (30 - 3)) & (1 << 3));
  1079.                 switch(funct3) {
  1080.                 case 0: /* add */
  1081.                     val = (intx_t)(val + val2);
  1082.                     break;
  1083.                 case 0 | 8: /* sub */
  1084.                     val = (intx_t)(val - val2);
  1085.                     break;
  1086.                 case 1: /* sll */
  1087.                     val = (intx_t)(val << (val2 & (XLEN - 1)));
  1088.                     break;
  1089.                 case 2: /* slt */
  1090.                     val = (target_long)val < (target_long)val2;
  1091.                     break;
  1092.                 case 3: /* sltu */
  1093.                     val = val < val2;
  1094.                     break;
  1095.                 case 4: /* xor */
  1096.                     val = val ^ val2;
  1097.                     break;
  1098.                 case 5: /* srl */
  1099.                     val = (intx_t)((uintx_t)val >> (val2 & (XLEN - 1)));
  1100.                     break;
  1101.                 case 5 | 8: /* sra */
  1102.                     val = (intx_t)val >> (val2 & (XLEN - 1));
  1103.                     break;
  1104.                 case 6: /* or */
  1105.                     val = val | val2;
  1106.                     break;
  1107.                 case 7: /* and */
  1108.                     val = val & val2;
  1109.                     break;
  1110.                 default:
  1111.                     goto illegal_insn;
  1112.                 }
  1113.             }
  1114.             if (rd != 0)
  1115.                 s->reg[rd] = val;
  1116.             NEXT_INSN;
  1117. #if XLEN >= 64
  1118.         case 0x3b: /* OP-32 */
  1119.             imm = insn >> 25;
  1120.             val = s->reg[rs1];
  1121.             val2 = s->reg[rs2];
  1122.             if (imm == 1) {
  1123.                 funct3 = (insn >> 12) & 7;
  1124.                 switch(funct3) {
  1125.                 case 0: /* mulw */
  1126.                     val = (int32_t)((int32_t)val * (int32_t)val2);
  1127.                     break;
  1128.                 case 4:/* divw */
  1129.                     val = div32(val, val2);
  1130.                     break;
  1131.                 case 5:/* divuw */
  1132.                     val = (int32_t)divu32(val, val2);
  1133.                     break;
  1134.                 case 6:/* remw */
  1135.                     val = rem32(val, val2);
  1136.                     break;
  1137.                 case 7:/* remuw */
  1138.                     val = (int32_t)remu32(val, val2);
  1139.                     break;
  1140.                 default:
  1141.                     goto illegal_insn;
  1142.                 }
  1143.             } else {
  1144.                 if (imm & ~0x20)
  1145.                     goto illegal_insn;
  1146.                 funct3 = ((insn >> 12) & 7) | ((insn >> (30 - 3)) & (1 << 3));
  1147.                 switch(funct3) {
  1148.                 case 0: /* addw */
  1149.                     val = (int32_t)(val + val2);
  1150.                     break;
  1151.                 case 0 | 8: /* subw */
  1152.                     val = (int32_t)(val - val2);
  1153.                     break;
  1154.                 case 1: /* sllw */
  1155.                     val = (int32_t)((uint32_t)val << (val2 & 31));
  1156.                     break;
  1157.                 case 5: /* srlw */
  1158.                     val = (int32_t)((uint32_t)val >> (val2 & 31));
  1159.                     break;
  1160.                 case 5 | 8: /* sraw */
  1161.                     val = (int32_t)val >> (val2 & 31);
  1162.                     break;
  1163.                 default:
  1164.                     goto illegal_insn;
  1165.                 }
  1166.             }
  1167.             if (rd != 0)
  1168.                 s->reg[rd] = val;
  1169.             NEXT_INSN;
  1170. #endif
  1171. #if XLEN >= 128
  1172.         case 0x7b: /* OP-64 */
  1173.             imm = insn >> 25;
  1174.             val = s->reg[rs1];
  1175.             val2 = s->reg[rs2];
  1176.             if (imm == 1) {
  1177.                 funct3 = (insn >> 12) & 7;
  1178.                 switch(funct3) {
  1179.                 case 0: /* muld */
  1180.                     val = (int64_t)((int64_t)val * (int64_t)val2);
  1181.                     break;
  1182.                 case 4:/* divd */
  1183.                     val = div64(val, val2);
  1184.                     break;
  1185.                 case 5:/* divud */
  1186.                     val = (int64_t)divu64(val, val2);
  1187.                     break;
  1188.                 case 6:/* remd */
  1189.                     val = rem64(val, val2);
  1190.                     break;
  1191.                 case 7:/* remud */
  1192.                     val = (int64_t)remu64(val, val2);
  1193.                     break;
  1194.                 default:
  1195.                     goto illegal_insn;
  1196.                 }
  1197.             } else {
  1198.                 if (imm & ~0x20)
  1199.                     goto illegal_insn;
  1200.                 funct3 = ((insn >> 12) & 7) | ((insn >> (30 - 3)) & (1 << 3));
  1201.                 switch(funct3) {
  1202.                 case 0: /* addd */
  1203.                     val = (int64_t)(val + val2);
  1204.                     break;
  1205.                 case 0 | 8: /* subd */
  1206.                     val = (int64_t)(val - val2);
  1207.                     break;
  1208.                 case 1: /* slld */
  1209.                     val = (int64_t)((uint64_t)val << (val2 & 63));
  1210.                     break;
  1211.                 case 5: /* srld */
  1212.                     val = (int64_t)((uint64_t)val >> (val2 & 63));
  1213.                     break;
  1214.                 case 5 | 8: /* srad */
  1215.                     val = (int64_t)val >> (val2 & 63);
  1216.                     break;
  1217.                 default:
  1218.                     goto illegal_insn;
  1219.                 }
  1220.             }
  1221.             if (rd != 0)
  1222.                 s->reg[rd] = val;
  1223.             NEXT_INSN;
  1224. #endif
  1225.         case 0x73:
  1226.             funct3 = (insn >> 12) & 7;
  1227.             imm = insn >> 20;
  1228.             if (funct3 & 4)
  1229.                 val = rs1;
  1230.             else
  1231.                 val = s->reg[rs1];
  1232.             funct3 &= 3;
  1233.             switch(funct3) {
  1234.             case 1: /* csrrw */
  1235.                 s->insn_counter = GET_INSN_COUNTER();
  1236.                 if (csr_read(s, &val2, imm, TRUE))
  1237.                     goto illegal_insn;
  1238.                 val2 = (intx_t)val2;
  1239.                 err = csr_write(s, imm, val);
  1240.                 if (err < 0)
  1241.                     goto illegal_insn;
  1242.                 if (rd != 0)
  1243.                     s->reg[rd] = val2;
  1244.                 if (err > 0) {
  1245.                     s->pc = GET_PC() + 4;
  1246.                     if (err == 2)
  1247.                         JUMP_INSN;
  1248.                     else
  1249.                         goto done_interp;
  1250.                 }
  1251.                 break;
  1252.             case 2: /* csrrs */
  1253.             case 3: /* csrrc */
  1254.                 s->insn_counter = GET_INSN_COUNTER();
  1255.                 if (csr_read(s, &val2, imm, (rs1 != 0)))
  1256.                     goto illegal_insn;
  1257.                 val2 = (intx_t)val2;
  1258.                 if (rs1 != 0) {
  1259.                     if (funct3 == 2)
  1260.                         val = val2 | val;
  1261.                     else
  1262.                         val = val2 & ~val;
  1263.                     err = csr_write(s, imm, val);
  1264.                     if (err < 0)
  1265.                         goto illegal_insn;
  1266.                 } else {
  1267.                     err = 0;
  1268.                 }
  1269.                 if (rd != 0)
  1270.                     s->reg[rd] = val2;
  1271.                 if (err > 0) {
  1272.                     s->pc = GET_PC() + 4;
  1273.                     if (err == 2)
  1274.                         JUMP_INSN;
  1275.                     else
  1276.                         goto done_interp;
  1277.                 }
  1278.                 break;
  1279.             case 0:
  1280.                 switch(imm) {
  1281.                 case 0x000: /* ecall */
  1282.                     if (insn & 0x000fff80)
  1283.                         goto illegal_insn;
  1284.                     s->pending_exception = CAUSE_USER_ECALL + s->priv;
  1285.                     goto exception;
  1286.                 case 0x001: /* ebreak */
  1287.                     if (insn & 0x000fff80)
  1288.                         goto illegal_insn;
  1289.                     s->pending_exception = CAUSE_BREAKPOINT;
  1290.                     goto exception;
  1291.                 case 0x102: /* sret */
  1292.                     {
  1293.                         if (insn & 0x000fff80)
  1294.                             goto illegal_insn;
  1295.                         if (s->priv < PRV_S)
  1296.                             goto illegal_insn;
  1297.                         s->pc = GET_PC();
  1298.                         handle_sret(s);
  1299.                         goto done_interp;
  1300.                     }
  1301.                     break;
  1302.                 case 0x302: /* mret */
  1303.                     {
  1304.                         if (insn & 0x000fff80)
  1305.                             goto illegal_insn;
  1306.                         if (s->priv < PRV_M)
  1307.                             goto illegal_insn;
  1308.                         s->pc = GET_PC();
  1309.                         handle_mret(s);
  1310.                         goto done_interp;
  1311.                     }
  1312.                     break;
  1313.                 case 0x105: /* wfi */
  1314.                     if (insn & 0x00007f80)
  1315.                         goto illegal_insn;
  1316.                     if (s->priv == PRV_U)
  1317.                         goto illegal_insn;
  1318.                     /* go to power down if no enabled interrupts are
  1319.                        pending */
  1320.                     if ((s->mip & s->mie) == 0) {
  1321.                         s->power_down_flag = TRUE;
  1322.                         s->pc = GET_PC() + 4;
  1323.                         goto done_interp;
  1324.                     }
  1325.                     break;
  1326.                 default:
  1327.                     if ((imm >> 5) == 0x09) {
  1328.                         /* sfence.vma */
  1329.                         if (insn & 0x00007f80)
  1330.                             goto illegal_insn;
  1331.                         if (s->priv == PRV_U)
  1332.                             goto illegal_insn;
  1333.                         if (rs1 == 0) {
  1334.                             tlb_flush_all(s);
  1335.                         } else {
  1336.                             tlb_flush_vaddr(s, s->reg[rs1]);
  1337.                         }
  1338.                         /* the current code TLB may have been flushed */
  1339.                         s->pc = GET_PC() + 4;
  1340.                         JUMP_INSN;
  1341.                     } else {
  1342.                         goto illegal_insn;
  1343.                     }
  1344.                     break;
  1345.                 }
  1346.                 break;
  1347.             default:
  1348.                 goto illegal_insn;
  1349.             }
  1350.             NEXT_INSN;
  1351.         case 0x0f: /* misc-mem */
  1352.             funct3 = (insn >> 12) & 7;
  1353.             switch(funct3) {
  1354.             case 0: /* fence */
  1355.                 if (insn & 0xf00fff80)
  1356.                     goto illegal_insn;
  1357.                 break;
  1358.             case 1: /* fence.i */
  1359.                 if (insn != 0x0000100f)
  1360.                     goto illegal_insn;
  1361.                 break;
  1362. #if XLEN >= 128
  1363.             case 2: /* lq */
  1364.                 imm = (int32_t)insn >> 20;
  1365.                 addr = s->reg[rs1] + imm;
  1366.                 if (target_read_u128(s, &val, addr))
  1367.                     goto mmu_exception;
  1368.                 if (rd != 0)
  1369.                     s->reg[rd] = val;
  1370.                 break;
  1371. #endif
  1372.             default:
  1373.                 goto illegal_insn;
  1374.             }
  1375.             NEXT_INSN;
  1376.         case 0x2f:
  1377.             funct3 = (insn >> 12) & 7;
  1378. #define OP_A(size)                                                      \
  1379.             {                                                           \
  1380.                 uint ## size ##_t rval;                                 \
  1381.                                                                         \
  1382.                 addr = s->reg[rs1];                                     \
  1383.                 funct3 = insn >> 27;                                    \
  1384.                 switch(funct3) {                                        \
  1385.                 case 2: /* lr.w */                                      \
  1386.                     if (rs2 != 0)                                       \
  1387.                         goto illegal_insn;                              \
  1388.                     if (target_read_u ## size(s, &rval, addr))          \
  1389.                         goto mmu_exception;                             \
  1390.                     val = (int## size ## _t)rval;                       \
  1391.                     s->load_res = addr;                                 \
  1392.                     break;                                              \
  1393.                 case 3: /* sc.w */                                      \
  1394.                     if (s->load_res == addr) {                          \
  1395.                         if (target_write_u ## size(s, addr, s->reg[rs2])) \
  1396.                             goto mmu_exception;                         \
  1397.                         val = 0;                                        \
  1398.                     } else {                                            \
  1399.                         val = 1;                                        \
  1400.                     }                                                   \
  1401.                     break;                                              \
  1402.                 case 1: /* amiswap.w */                                 \
  1403.                 case 0: /* amoadd.w */                                  \
  1404.                 case 4: /* amoxor.w */                                  \
  1405.                 case 0xc: /* amoand.w */                                \
  1406.                 case 0x8: /* amoor.w */                                 \
  1407.                 case 0x10: /* amomin.w */                               \
  1408.                 case 0x14: /* amomax.w */                               \
  1409.                 case 0x18: /* amominu.w */                              \
  1410.                 case 0x1c: /* amomaxu.w */                              \
  1411.                     if (target_read_u ## size(s, &rval, addr))          \
  1412.                         goto mmu_exception;                             \
  1413.                     val = (int## size ## _t)rval;                       \
  1414.                     val2 = s->reg[rs2];                                 \
  1415.                     switch(funct3) {                                    \
  1416.                     case 1: /* amiswap.w */                             \
  1417.                         break;                                          \
  1418.                     case 0: /* amoadd.w */                              \
  1419.                         val2 = (int## size ## _t)(val + val2);          \
  1420.                         break;                                          \
  1421.                     case 4: /* amoxor.w */                              \
  1422.                         val2 = (int## size ## _t)(val ^ val2);          \
  1423.                         break;                                          \
  1424.                     case 0xc: /* amoand.w */                            \
  1425.                         val2 = (int## size ## _t)(val & val2);          \
  1426.                         break;                                          \
  1427.                     case 0x8: /* amoor.w */                             \
  1428.                         val2 = (int## size ## _t)(val | val2);          \
  1429.                         break;                                          \
  1430.                     case 0x10: /* amomin.w */                           \
  1431.                         if ((int## size ## _t)val < (int## size ## _t)val2) \
  1432.                             val2 = (int## size ## _t)val;               \
  1433.                         break;                                          \
  1434.                     case 0x14: /* amomax.w */                           \
  1435.                         if ((int## size ## _t)val > (int## size ## _t)val2) \
  1436.                             val2 = (int## size ## _t)val;               \
  1437.                         break;                                          \
  1438.                     case 0x18: /* amominu.w */                          \
  1439.                         if ((uint## size ## _t)val < (uint## size ## _t)val2) \
  1440.                             val2 = (int## size ## _t)val;               \
  1441.                         break;                                          \
  1442.                     case 0x1c: /* amomaxu.w */                          \
  1443.                         if ((uint## size ## _t)val > (uint## size ## _t)val2) \
  1444.                             val2 = (int## size ## _t)val;               \
  1445.                         break;                                          \
  1446.                     default:                                            \
  1447.                         goto illegal_insn;                              \
  1448.                     }                                                   \
  1449.                     if (target_write_u ## size(s, addr, val2))          \
  1450.                         goto mmu_exception;                             \
  1451.                     break;                                              \
  1452.                 default:                                                \
  1453.                     goto illegal_insn;                                  \
  1454.                 }                                                       \
  1455.             }
  1456.  
  1457.             switch(funct3) {
  1458.             case 2:
  1459.                 OP_A(32);
  1460.                 break;
  1461. #if XLEN >= 64
  1462.             case 3:
  1463.                 OP_A(64);
  1464.                 break;
  1465. #endif
  1466. #if XLEN >= 128
  1467.             case 4:
  1468.                 OP_A(128);
  1469.                 break;
  1470. #endif
  1471.             default:
  1472.                 goto illegal_insn;
  1473.             }
  1474.             if (rd != 0)
  1475.                 s->reg[rd] = val;
  1476.             NEXT_INSN;
  1477. #if FLEN > 0
  1478.             /* FPU */
  1479.         case 0x07: /* fp load */
  1480.             if (s->fs == 0)
  1481.                 goto illegal_insn;
  1482.             funct3 = (insn >> 12) & 7;
  1483.             imm = (int32_t)insn >> 20;
  1484.             addr = s->reg[rs1] + imm;
  1485.             switch(funct3) {
  1486.             case 2: /* flw */
  1487.                 {
  1488.                     uint32_t rval;
  1489.                     if (target_read_u32(s, &rval, addr))
  1490.                         goto mmu_exception;
  1491.                     s->fp_reg[rd] = rval | F32_HIGH;
  1492.                 }
  1493.                 break;
  1494. #if FLEN >= 64
  1495.             case 3: /* fld */
  1496.                 {
  1497.                     uint64_t rval;
  1498.                     if (target_read_u64(s, &rval, addr))
  1499.                         goto mmu_exception;
  1500.                     s->fp_reg[rd] = rval | F64_HIGH;
  1501.                 }
  1502.                 break;
  1503. #endif
  1504. #if FLEN >= 128
  1505.             case 4: /* flq */
  1506.                 {
  1507.                     uint128_t rval;
  1508.                     if (target_read_u128(s, &rval, addr))
  1509.                         goto mmu_exception;
  1510.                     s->fp_reg[rd] = rval;
  1511.                 }
  1512.                 break;
  1513. #endif
  1514.             default:
  1515.                 goto illegal_insn;
  1516.             }
  1517.             s->fs = 3;
  1518.             NEXT_INSN;
  1519.         case 0x27: /* fp store */
  1520.             if (s->fs == 0)
  1521.                 goto illegal_insn;
  1522.             funct3 = (insn >> 12) & 7;
  1523.             imm = rd | ((insn >> (25 - 5)) & 0xfe0);
  1524.             imm = (imm << 20) >> 20;
  1525.             addr = s->reg[rs1] + imm;
  1526.             switch(funct3) {
  1527.             case 2: /* fsw */
  1528.                 if (target_write_u32(s, addr, s->fp_reg[rs2]))
  1529.                     goto mmu_exception;
  1530.                 break;
  1531. #if FLEN >= 64
  1532.             case 3: /* fsd */
  1533.                 if (target_write_u64(s, addr, s->fp_reg[rs2]))
  1534.                     goto mmu_exception;
  1535.                 break;
  1536. #endif
  1537. #if FLEN >= 128
  1538.             case 4: /* fsq */
  1539.                 if (target_write_u128(s, addr, s->fp_reg[rs2]))
  1540.                     goto mmu_exception;
  1541.                 break;
  1542. #endif
  1543.             default:
  1544.                 goto illegal_insn;
  1545.             }
  1546.             NEXT_INSN;
  1547.         case 0x43: /* fmadd */
  1548.             if (s->fs == 0)
  1549.                 goto illegal_insn;
  1550.             funct3 = (insn >> 25) & 3;
  1551.             rs3 = insn >> 27;
  1552.             rm = get_insn_rm(s, (insn >> 12) & 7);
  1553.             if (rm < 0)
  1554.                 goto illegal_insn;
  1555.             switch(funct3) {
  1556.             case 0:
  1557.                 s->fp_reg[rd] = fma_sf32(s->fp_reg[rs1], s->fp_reg[rs2],
  1558.                                          s->fp_reg[rs3], rm, &s->fflags) | F32_HIGH;
  1559.                 break;
  1560. #if FLEN >= 64
  1561.             case 1:
  1562.                 s->fp_reg[rd] = fma_sf64(s->fp_reg[rs1], s->fp_reg[rs2],
  1563.                                          s->fp_reg[rs3], rm, &s->fflags) | F64_HIGH;
  1564.                 break;
  1565. #endif
  1566. #if FLEN >= 128
  1567.             case 3:
  1568.                 s->fp_reg[rd] = fma_sf128(s->fp_reg[rs1], s->fp_reg[rs2],
  1569.                                           s->fp_reg[rs3], rm, &s->fflags);
  1570.                 break;
  1571. #endif
  1572.             default:
  1573.                 goto illegal_insn;
  1574.             }
  1575.             s->fs = 3;
  1576.             NEXT_INSN;
  1577.         case 0x47: /* fmsub */
  1578.             if (s->fs == 0)
  1579.                 goto illegal_insn;
  1580.             funct3 = (insn >> 25) & 3;
  1581.             rs3 = insn >> 27;
  1582.             rm = get_insn_rm(s, (insn >> 12) & 7);
  1583.             if (rm < 0)
  1584.                 goto illegal_insn;
  1585.             switch(funct3) {
  1586.             case 0:
  1587.                 s->fp_reg[rd] = fma_sf32(s->fp_reg[rs1],
  1588.                                          s->fp_reg[rs2],
  1589.                                          s->fp_reg[rs3] ^ FSIGN_MASK32,
  1590.                                          rm, &s->fflags) | F32_HIGH;
  1591.                 break;
  1592. #if FLEN >= 64
  1593.             case 1:
  1594.                 s->fp_reg[rd] = fma_sf64(s->fp_reg[rs1],
  1595.                                          s->fp_reg[rs2],
  1596.                                          s->fp_reg[rs3] ^ FSIGN_MASK64,
  1597.                                          rm, &s->fflags) | F64_HIGH;
  1598.                 break;
  1599. #endif
  1600. #if FLEN >= 128
  1601.             case 3:
  1602.                 s->fp_reg[rd] = fma_sf128(s->fp_reg[rs1],
  1603.                                           s->fp_reg[rs2],
  1604.                                           s->fp_reg[rs3] ^ FSIGN_MASK128,
  1605.                                           rm, &s->fflags);
  1606.                 break;
  1607. #endif
  1608.             default:
  1609.                 goto illegal_insn;
  1610.             }
  1611.             s->fs = 3;
  1612.             NEXT_INSN;
  1613.         case 0x4b: /* fnmsub */
  1614.             if (s->fs == 0)
  1615.                 goto illegal_insn;
  1616.             funct3 = (insn >> 25) & 3;
  1617.             rs3 = insn >> 27;
  1618.             rm = get_insn_rm(s, (insn >> 12) & 7);
  1619.             if (rm < 0)
  1620.                 goto illegal_insn;
  1621.             switch(funct3) {
  1622.             case 0:
  1623.                 s->fp_reg[rd] = fma_sf32(s->fp_reg[rs1] ^ FSIGN_MASK32,
  1624.                                          s->fp_reg[rs2],
  1625.                                          s->fp_reg[rs3],
  1626.                                          rm, &s->fflags) | F32_HIGH;
  1627.                 break;
  1628. #if FLEN >= 64
  1629.             case 1:
  1630.                 s->fp_reg[rd] = fma_sf64(s->fp_reg[rs1] ^ FSIGN_MASK64,
  1631.                                          s->fp_reg[rs2],
  1632.                                          s->fp_reg[rs3],
  1633.                                          rm, &s->fflags) | F64_HIGH;
  1634.                 break;
  1635. #endif
  1636. #if FLEN >= 128
  1637.             case 3:
  1638.                 s->fp_reg[rd] = fma_sf128(s->fp_reg[rs1] ^ FSIGN_MASK128,
  1639.                                           s->fp_reg[rs2],
  1640.                                           s->fp_reg[rs3],
  1641.                                           rm, &s->fflags);
  1642.                 break;
  1643. #endif
  1644.             default:
  1645.                 goto illegal_insn;
  1646.             }
  1647.             s->fs = 3;
  1648.             NEXT_INSN;
  1649.         case 0x4f: /* fnmadd */
  1650.             if (s->fs == 0)
  1651.                 goto illegal_insn;
  1652.             funct3 = (insn >> 25) & 3;
  1653.             rs3 = insn >> 27;
  1654.             rm = get_insn_rm(s, (insn >> 12) & 7);
  1655.             if (rm < 0)
  1656.                 goto illegal_insn;
  1657.             switch(funct3) {
  1658.             case 0:
  1659.                 s->fp_reg[rd] = fma_sf32(s->fp_reg[rs1] ^ FSIGN_MASK32,
  1660.                                          s->fp_reg[rs2],
  1661.                                          s->fp_reg[rs3] ^ FSIGN_MASK32,
  1662.                                          rm, &s->fflags) | F32_HIGH;
  1663.                 break;
  1664. #if FLEN >= 64
  1665.             case 1:
  1666.                 s->fp_reg[rd] = fma_sf64(s->fp_reg[rs1] ^ FSIGN_MASK64,
  1667.                                          s->fp_reg[rs2],
  1668.                                          s->fp_reg[rs3] ^ FSIGN_MASK64,
  1669.                                          rm, &s->fflags) | F64_HIGH;
  1670.                 break;
  1671. #endif
  1672. #if FLEN >= 128
  1673.             case 3:
  1674.                 s->fp_reg[rd] = fma_sf128(s->fp_reg[rs1] ^ FSIGN_MASK128,
  1675.                                           s->fp_reg[rs2],
  1676.                                           s->fp_reg[rs3] ^ FSIGN_MASK128,
  1677.                                           rm, &s->fflags);
  1678.                 break;
  1679. #endif
  1680.             default:
  1681.                 goto illegal_insn;
  1682.             }
  1683.             s->fs = 3;
  1684.             NEXT_INSN;
  1685.         case 0x53:
  1686.             if (s->fs == 0)
  1687.                 goto illegal_insn;
  1688.             imm = insn >> 25;
  1689.             rm = (insn >> 12) & 7;
  1690.             switch(imm) {
  1691.  
  1692. #define F_SIZE 32
  1693. #include "riscv_cpu_fp_template.h"
  1694. #if FLEN >= 64
  1695. #define F_SIZE 64
  1696. #include "riscv_cpu_fp_template.h"
  1697. #endif
  1698. #if FLEN >= 128
  1699. #define F_SIZE 128
  1700. #include "riscv_cpu_fp_template.h"
  1701. #endif
  1702.  
  1703.             default:
  1704.                 goto illegal_insn;
  1705.             }
  1706.             NEXT_INSN;
  1707. #endif
  1708.         default:
  1709.             goto illegal_insn;
  1710.         }
  1711.         /* update PC for next instruction */
  1712.     jump_insn: ;
  1713.     } /* end of main loop */
  1714.  illegal_insn:
  1715.     s->pending_exception = CAUSE_ILLEGAL_INSTRUCTION;
  1716.     s->pending_tval = insn;
  1717.  mmu_exception:
  1718.  exception:
  1719.     s->pc = GET_PC();
  1720.     if (s->pending_exception >= 0) {
  1721.         /* Note: the idea is that one exception counts for one cycle. */
  1722.         s->n_cycles--;
  1723.         raise_exception2(s, s->pending_exception, s->pending_tval);
  1724.     }
  1725.     /* we exit because XLEN may have changed */
  1726.  done_interp:
  1727. the_end:
  1728.     s->insn_counter = GET_INSN_COUNTER();
  1729. #if 0
  1730.     printf("done interp %lx int=%x mstatus=%lx prv=%d\n",
  1731.            (uint64_t)s->insn_counter, s->mip & s->mie, (uint64_t)s->mstatus,
  1732.            s->priv);
  1733. #endif
  1734. }
  1735.  
  1736. #undef uintx_t
  1737. #undef intx_t
  1738. #undef XLEN
  1739. #undef OP_A
  1740.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement