@@ -656,39 +656,35 @@ class Assembler : public AbstractAssembler {
656
656
657
657
#undef INSN
658
658
659
- #define INSN (NAME, op ) \
660
- void NAME (Register Rd, const int32_t offset) { \
661
- guarantee (is_simm21 (offset) && ((offset % 2 ) == 0 ), " offset is invalid." ); \
662
- unsigned insn = 0 ; \
663
- patch ((address)&insn, 6 , 0 , op); \
664
- patch_reg ((address)&insn, 7 , Rd); \
665
- patch ((address)&insn, 19 , 12 , (uint32_t )((offset >> 12 ) & 0xff )); \
666
- patch ((address)&insn, 20 , (uint32_t )((offset >> 11 ) & 0x1 )); \
667
- patch ((address)&insn, 30 , 21 , (uint32_t )((offset >> 1 ) & 0x3ff )); \
668
- patch ((address)&insn, 31 , (uint32_t )((offset >> 20 ) & 0x1 )); \
669
- emit (insn); \
659
+ private:
660
+ // All calls and jumps must go via MASM.
661
+ // Format J-type
662
+ void _jal (Register Rd, const int32_t offset) {
663
+ guarantee (is_simm21 (offset) && ((offset % 2 ) == 0 ), " offset is invalid." );
664
+ unsigned insn = 0 ;
665
+ patch ((address)&insn, 6 , 0 , 0b1101111 );
666
+ patch_reg ((address)&insn, 7 , Rd);
667
+ patch ((address)&insn, 19 , 12 , (uint32_t )((offset >> 12 ) & 0xff ));
668
+ patch ((address)&insn, 20 , (uint32_t )((offset >> 11 ) & 0x1 ));
669
+ patch ((address)&insn, 30 , 21 , (uint32_t )((offset >> 1 ) & 0x3ff ));
670
+ patch ((address)&insn, 31 , (uint32_t )((offset >> 20 ) & 0x1 ));
671
+ emit (insn);
670
672
}
671
673
672
- INSN (jal, 0b1101111 );
673
-
674
- #undef INSN
675
-
676
- #define INSN (NAME, op, funct ) \
677
- void NAME (Register Rd, Register Rs, const int32_t offset) { \
678
- guarantee (is_simm12 (offset), " offset is invalid." ); \
679
- unsigned insn = 0 ; \
680
- patch ((address)&insn, 6 , 0 , op); \
681
- patch_reg ((address)&insn, 7 , Rd); \
682
- patch ((address)&insn, 14 , 12 , funct); \
683
- patch_reg ((address)&insn, 15 , Rs); \
684
- int32_t val = offset & 0xfff ; \
685
- patch ((address)&insn, 31 , 20 , val); \
686
- emit (insn); \
674
+ // Format I-type
675
+ void _jalr (Register Rd, Register Rs, const int32_t offset) {
676
+ guarantee (is_simm12 (offset), " offset is invalid." );
677
+ unsigned insn = 0 ;
678
+ patch ((address)&insn, 6 , 0 , 0b1100111 );
679
+ patch_reg ((address)&insn, 7 , Rd);
680
+ patch ((address)&insn, 14 , 12 , 0b000 );
681
+ patch_reg ((address)&insn, 15 , Rs);
682
+ int32_t val = offset & 0xfff ;
683
+ patch ((address)&insn, 31 , 20 , val);
684
+ emit (insn);
687
685
}
688
686
689
- INSN (_jalr, 0b1100111 , 0b000 );
690
-
691
- #undef INSN
687
+ public:
692
688
693
689
enum barrier {
694
690
i = 0b1000 , o = 0b0100 , r = 0b0010 , w = 0b0001 ,
@@ -2294,21 +2290,23 @@ enum Nf {
2294
2290
2295
2291
#undef INSN
2296
2292
2297
- #define INSN (NAME, funct4, op ) \
2298
- void NAME (Register Rs1) { \
2299
- assert_cond (Rs1 != x0); \
2300
- uint16_t insn = 0 ; \
2301
- c_patch ((address)&insn, 1 , 0 , op); \
2302
- c_patch_reg ((address)&insn, 2 , x0); \
2303
- c_patch_reg ((address)&insn, 7 , Rs1); \
2304
- c_patch ((address)&insn, 15 , 12 , funct4); \
2305
- emit_int16 (insn); \
2293
+ private:
2294
+ // All calls and jumps must go via MASM.
2295
+ // Format CR, c.jr/c.jalr
2296
+ // Note C instruction can't be changed, i.e. relocation patching.
2297
+ template <uint8_t InstructionType, uint8_t FunctionType>
2298
+ void c_cr_if (Register Rs1) {
2299
+ assert_cond (Rs1 != x0);
2300
+ uint16_t insn = 0 ;
2301
+ c_patch ((address)&insn, 1 , 0 , FunctionType);
2302
+ c_patch_reg ((address)&insn, 2 , x0);
2303
+ c_patch_reg ((address)&insn, 7 , Rs1);
2304
+ c_patch ((address)&insn, 15 , 12 , InstructionType);
2305
+ emit_int16 (insn);
2306
2306
}
2307
2307
2308
- INSN (c_jr, 0b1000 , 0b10 );
2309
- INSN (c_jalr, 0b1001 , 0b10 );
2310
-
2311
- #undef INSN
2308
+ void c_jr (Register Rs1) { c_cr_if<0b1000 , 0b10 >(Rs1); }
2309
+ void c_jalr (Register Rs1) { c_cr_if<0b1001 , 0b10 >(Rs1); }
2312
2310
2313
2311
typedef void (Assembler::* j_c_insn)(address dest);
2314
2312
typedef void (Assembler::* compare_and_branch_c_insn)(Register Rs1, address dest);
@@ -2331,35 +2329,36 @@ enum Nf {
2331
2329
}
2332
2330
}
2333
2331
2334
- #define INSN (NAME, funct3, op ) \
2335
- void NAME (int32_t offset) { \
2336
- assert (is_simm12 (offset) && ((offset % 2 ) == 0 ), " invalid encoding" ); \
2337
- uint16_t insn = 0 ; \
2338
- c_patch ((address)&insn, 1 , 0 , op); \
2339
- c_patch ((address)&insn, 2 , 2 , (offset & nth_bit (5 )) >> 5 ); \
2340
- c_patch ((address)&insn, 5 , 3 , (offset & right_n_bits (4 )) >> 1 ); \
2341
- c_patch ((address)&insn, 6 , 6 , (offset & nth_bit (7 )) >> 7 ); \
2342
- c_patch ((address)&insn, 7 , 7 , (offset & nth_bit (6 )) >> 6 ); \
2343
- c_patch ((address)&insn, 8 , 8 , (offset & nth_bit (10 )) >> 10 ); \
2344
- c_patch ((address)&insn, 10 , 9 , (offset & right_n_bits (10 )) >> 8 ); \
2345
- c_patch ((address)&insn, 11 , 11 , (offset & nth_bit (4 )) >> 4 ); \
2346
- c_patch ((address)&insn, 12 , 12 , (offset & nth_bit (11 )) >> 11 ); \
2347
- c_patch ((address)&insn, 15 , 13 , funct3); \
2348
- emit_int16 (insn); \
2349
- } \
2350
- void NAME (address dest) { \
2351
- assert_cond (dest != nullptr ); \
2352
- int64_t distance = dest - pc (); \
2353
- assert (is_simm12 (distance) && ((distance % 2 ) == 0 ), " invalid encoding" ); \
2354
- c_j (distance); \
2355
- } \
2356
- void NAME (Label &L) { \
2357
- wrap_label (L, &Assembler::NAME); \
2332
+ // Format CJ, c.j (c.jal)
2333
+ // Note C instruction can't be changed, i.e. relocation patching.
2334
+ void c_j (int32_t offset) {
2335
+ assert (is_simm12 (offset) && ((offset % 2 ) == 0 ), " invalid encoding" );
2336
+ uint16_t insn = 0 ;
2337
+ c_patch ((address)&insn, 1 , 0 , 0b01 );
2338
+ c_patch ((address)&insn, 2 , 2 , (offset & nth_bit (5 )) >> 5 );
2339
+ c_patch ((address)&insn, 5 , 3 , (offset & right_n_bits (4 )) >> 1 );
2340
+ c_patch ((address)&insn, 6 , 6 , (offset & nth_bit (7 )) >> 7 );
2341
+ c_patch ((address)&insn, 7 , 7 , (offset & nth_bit (6 )) >> 6 );
2342
+ c_patch ((address)&insn, 8 , 8 , (offset & nth_bit (10 )) >> 10 );
2343
+ c_patch ((address)&insn, 10 , 9 , (offset & right_n_bits (10 )) >> 8 );
2344
+ c_patch ((address)&insn, 11 , 11 , (offset & nth_bit (4 )) >> 4 );
2345
+ c_patch ((address)&insn, 12 , 12 , (offset & nth_bit (11 )) >> 11 );
2346
+ c_patch ((address)&insn, 15 , 13 , 0b101 );
2347
+ emit_int16 (insn);
2358
2348
}
2359
2349
2360
- INSN (c_j, 0b101 , 0b01 );
2350
+ void c_j (address dest) {
2351
+ assert_cond (dest != nullptr );
2352
+ int64_t distance = dest - pc ();
2353
+ assert (is_simm12 (distance) && ((distance % 2 ) == 0 ), " invalid encoding" );
2354
+ c_j (distance);
2355
+ }
2361
2356
2362
- #undef INSN
2357
+ void c_j (Label &L) {
2358
+ wrap_label (L, &Assembler::c_j);
2359
+ }
2360
+
2361
+ public:
2363
2362
2364
2363
#define INSN (NAME, funct3, op ) \
2365
2364
void NAME (Register Rs1, int32_t imm) { \
@@ -2812,24 +2811,35 @@ enum Nf {
2812
2811
// --------------------------
2813
2812
// Unconditional branch instructions
2814
2813
// --------------------------
2815
- #define INSN (NAME ) \
2816
- void NAME (Register Rd, Register Rs, const int32_t offset) { \
2817
- /* jalr -> c.jr/c.jalr */ \
2818
- if (do_compress () && (offset == 0 && Rs != x0)) { \
2819
- if (Rd == x1) { \
2820
- c_jalr (Rs); \
2821
- return ; \
2822
- } else if (Rd == x0) { \
2823
- c_jr (Rs); \
2824
- return ; \
2825
- } \
2826
- } \
2827
- _jalr (Rd, Rs, offset); \
2814
+ protected:
2815
+ // All calls and jumps must go via MASM.
2816
+ void jalr (Register Rd, Register Rs, const int32_t offset) {
2817
+ /* jalr -> c.jr/c.jalr */
2818
+ if (do_compress () && (offset == 0 && Rs != x0)) {
2819
+ if (Rd == x1) {
2820
+ c_jalr (Rs);
2821
+ return ;
2822
+ } else if (Rd == x0) {
2823
+ c_jr (Rs);
2824
+ return ;
2825
+ }
2826
+ }
2827
+ _jalr (Rd, Rs, offset);
2828
2828
}
2829
2829
2830
- INSN (jalr);
2830
+ void jal (Register Rd, const int32_t offset) {
2831
+ /* jal -> c.j, note c.jal is RV32C only */
2832
+ if (do_compress () &&
2833
+ Rd == x0 &&
2834
+ is_simm12 (offset) && ((offset % 2 ) == 0 )) {
2835
+ c_j (offset);
2836
+ return ;
2837
+ }
2831
2838
2832
- #undef INSN
2839
+ _jal (Rd, offset);
2840
+ }
2841
+
2842
+ public:
2833
2843
2834
2844
// --------------------------
2835
2845
// Miscellaneous Instructions
@@ -3009,18 +3019,6 @@ enum Nf {
3009
3019
3010
3020
#undef INSN
3011
3021
3012
- // ---------------------------------------------------------------------------------------
3013
-
3014
- #define INSN (NAME, REGISTER ) \
3015
- void NAME (Register Rs) { \
3016
- jalr (REGISTER, Rs, 0 ); \
3017
- }
3018
-
3019
- INSN (jr, x0);
3020
- INSN (jalr, x1);
3021
-
3022
- #undef INSN
3023
-
3024
3022
// -------------- ZCB Instruction Definitions --------------
3025
3023
// Zcb additional C instructions
3026
3024
private:
0 commit comments