History

riscv: Add pseudoinstructions

call, tail, jump, jr, mv, not, neg, negw, seqz, snez, sltz, sgtz, bnez, beqz, blez, bgez, bltz, bgtz, li

Ekaitz Zarraga committed 2 years ago

Commit 8bfef6a1 parent 8cbbd2b2 files · +197 −4Browse files

Unified · Split

2 files
  1. riscv64-asm.c +195 −4
  2. riscv64-tok.h +2 −0
riscv64-asm.c+195−4
@@ -152,6 +152,12 @@ static void asm_nullary_opcode(TCCState *s1, int token) · 151 unmodified lines
152 asm_emit_opcode((0x1C << 2) | 3 | (0x105 << 20));152 asm_emit_opcode((0x1C << 2) | 3 | (0x105 << 20));
153 return;153 return;
154 154
155 /* Pseudoinstructions */
156 case TOK_ASM_ret:
157 /* jalr zero, x1, 0 */
158 asm_emit_opcode( 0x67 | (0 << 12) | ENCODE_RS1(1) );
159 return;
160
155 /* C extension */161 /* C extension */
156 case TOK_ASM_c_ebreak:162 case TOK_ASM_c_ebreak:
157 asm_emit_cr(token, 2 | (9 << 12), &nil, &nil);163 asm_emit_cr(token, 2 | (9 << 12), &nil, &nil);
@@ -265,7 +271,8 @@ static void asm_unary_opcode(TCCState *s1, int token) · 107 unmodified lines
265{271{
266 uint32_t opcode = (0x1C << 2) | 3 | (2 << 12);272 uint32_t opcode = (0x1C << 2) | 3 | (2 << 12);
267 Operand op;273 Operand op;
268 static const Operand nil = {.type = OP_REG};274 static const Operand zero = {.type = OP_REG};
275 static const Operand zimm = {.type = OP_IM12S};
269 276
270 parse_operands(s1, &op, 1);277 parse_operands(s1, &op, 1);
271 /* Note: Those all map to CSR--so they are pseudo-instructions. */278 /* Note: Those all map to CSR--so they are pseudo-instructions. */
@@ -291,6 +298,26 @@ static void asm_unary_opcode(TCCState *s1, int token) · 19 unmodified lines
291 case TOK_ASM_rdinstreth:298 case TOK_ASM_rdinstreth:
292 asm_emit_opcode(opcode | (0xC82 << 20) | ENCODE_RD(op.reg));299 asm_emit_opcode(opcode | (0xC82 << 20) | ENCODE_RD(op.reg));
293 return;300 return;
301
302 case TOK_ASM_jr:
303 /* jalr zero, 0(rs)*/
304 asm_emit_i(token, 0x67 | (0 << 12), &zero, &op, &zimm);
305 return;
306 case TOK_ASM_call:
307 /* auipc ra, 0 */
308 greloca(cur_text_section, op.e.sym, ind, R_RISCV_CALL, 0);
309 asm_emit_opcode(3 | (5 << 2) | ENCODE_RD(1));
310 /* jalr zero, 0(ra) */
311 asm_emit_opcode(0x67 | (0 << 12) | ENCODE_RS1(1));
312 return;
313 case TOK_ASM_tail:
314 /* auipc x6, 0 */
315 greloca(cur_text_section, op.e.sym, ind, R_RISCV_CALL, 0);
316 asm_emit_opcode(3 | (5 << 2) | ENCODE_RD(6));
317 /* jalr zero, 0(x6) */
318 asm_emit_opcode(0x67 | (0 << 12) | ENCODE_RS1(6));
319 return;
320
294 /* C extension */321 /* C extension */
295 case TOK_ASM_c_j:322 case TOK_ASM_c_j:
296 asm_emit_cj(token, 1 | (5 << 13), &op);323 asm_emit_cj(token, 1 | (5 << 13), &op);
@@ -299,10 +326,10 @@ static void asm_unary_opcode(TCCState *s1, int token) · 2 unmodified lines
299 asm_emit_cj(token, 1 | (1 << 13), &op);326 asm_emit_cj(token, 1 | (1 << 13), &op);
300 return;327 return;
301 case TOK_ASM_c_jalr:328 case TOK_ASM_c_jalr:
302 asm_emit_cr(token, 2 | (9 << 12), &op, &nil);329 asm_emit_cr(token, 2 | (9 << 12), &op, &zero);
303 return;330 return;
304 case TOK_ASM_c_jr:331 case TOK_ASM_c_jr:
305 asm_emit_cr(token, 2 | (8 << 12), &op, &nil);332 asm_emit_cr(token, 2 | (8 << 12), &op, &zero);
306 return;333 return;
307 default:334 default:
308 expect("unary instruction");335 expect("unary instruction");
@@ -331,6 +358,8 @@ static void asm_emit_u(int token, uint32_t opcode, const Operand* rd, const Oper · 22 unmodified lines
331 358
332static void asm_binary_opcode(TCCState* s1, int token)359static void asm_binary_opcode(TCCState* s1, int token)
333{360{
361 static const Operand zero = {.type = OP_REG, .reg = 0};
362 Operand imm = {.type = OP_IM12S, .e = {.v = 0}};
334 Operand ops[2];363 Operand ops[2];
335 parse_operands(s1, &ops[0], 2);364 parse_operands(s1, &ops[0], 2);
336 365
@@ -452,6 +481,110 @@ static void asm_binary_opcode(TCCState* s1, int token) · 115 unmodified lines
452 /* addi rd, rd, 0 */481 /* addi rd, rd, 0 */
453 asm_emit_i(token, 3 | (4 << 2), ops, ops, ops + 1);482 asm_emit_i(token, 3 | (4 << 2), ops, ops, ops + 1);
454 return;483 return;
484 case TOK_ASM_li:
485 if(ops[1].type != OP_IM32 && ops[1].type != OP_IM12S){
486 tcc_error("'%s': Expected first source operand that is an immediate value between 0 and 0xFFFFFFFFFFFFFFFF", get_tok_str(token, NULL));
487 }
488 int32_t lo = ops[1].e.v;
489 uint32_t hi = (int64_t)ops[1].e.v >> 32;
490 if(lo < 0){
491 hi += 1;
492 }
493 imm.e.v = ((hi + 0x800) & 0xfffff000) >> 12;
494 /* lui rd, HI_20(HI_32(imm)) */
495 asm_emit_u(token, (0xD << 2) | 3, &ops[0], &imm);
496 /* addi rd, rd, LO_12(HI_32(imm)) */
497 imm.e.v = (int32_t)hi<<20>>20;
498 asm_emit_i(token, 3 | (4 << 2), &ops[0], &ops[0], &imm);
499 /* slli rd, rd, 12 */
500 imm.e.v = 12;
501 asm_emit_i(token, (4 << 2) | 3 | (1 << 12), &ops[0], &ops[0], &imm);
502 /* addi rd, rd, HI_12(LO_32(imm)) */
503 imm.e.v = (lo + (1<<19)) >> 20;
504 asm_emit_i(token, 3 | (4 << 2), &ops[0], &ops[0], &imm);
505 /* slli rd, rd, 12 */
506 imm.e.v = 12;
507 asm_emit_i(token, (4 << 2) | 3 | (1 << 12), &ops[0], &ops[0], &imm);
508 /* addi rd, rd, HI_12(LO_20(LO_32imm)) */
509 lo = lo << 12 >> 12;
510 imm.e.v = lo >> 8;
511 asm_emit_i(token, 3 | (4 << 2), &ops[0], &ops[0], &imm);
512 /* slli rd, rd, 8 */
513 imm.e.v = 8;
514 asm_emit_i(token, (4 << 2) | 3 | (1 << 12), &ops[0], &ops[0], &imm);
515 /* addi rd, rd, LO_8(LO_20(LO_32imm)) */
516 lo &= 0xff;
517 imm.e.v = lo << 20 >> 20;
518 asm_emit_i(token, 3 | (4 << 2), &ops[0], &ops[0], &imm);
519 return;
520 case TOK_ASM_mv:
521 /* addi rd, rs, 0 */
522 asm_emit_i(token, 3 | (4 << 2), &ops[0], &ops[1], &imm);
523 return;
524 case TOK_ASM_not:
525 /* xori rd, rs, -1 */
526 imm.e.v = -1;
527 asm_emit_i(token, (0x4 << 2) | 3 | (4 << 12), &ops[0], &ops[1], &imm);
528 return;
529 case TOK_ASM_neg:
530 /* sub rd, x0, rs */
531 imm.e.v = 1;
532 asm_emit_i(token, (0x4 << 2) | 3 | (4 << 12), &ops[0], &zero, &imm);
533 return;
534 case TOK_ASM_negw:
535 /* sub rd, x0, rs */
536 imm.e.v = 1;
537 asm_emit_i(token, (0x4 << 2) | 3 | (4 << 12), &ops[0], &zero, &imm);
538 return;
539 case TOK_ASM_jump:
540 /* auipc x5, 0 */
541 asm_emit_opcode(3 | (5 << 2) | ENCODE_RD(5));
542 greloca(cur_text_section, ops->e.sym, ind, R_RISCV_CALL, 0);
543 /* jalr zero, 0(x5) */
544 asm_emit_opcode(0x67 | (0 << 12) | ENCODE_RS1(5));
545 return;
546 case TOK_ASM_seqz:
547 /* sltiu rd, rs, 1 */
548 imm.e.v = 1;
549 asm_emit_i(token, (0x4 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &imm);
550 return;
551 case TOK_ASM_snez:
552 /* sltu rd, zero, rs */
553 imm.e.v = 1;
554 asm_emit_r(token, (0xC << 2) | 3 | (3 << 12), &ops[0], &zero, &ops[1]);
555 return;
556 case TOK_ASM_sltz:
557 /* slt rd, rs, zero */
558 asm_emit_r(token, (0xC << 2) | 3 | (2 << 12), &ops[0], &ops[1], &zero);
559 return;
560 case TOK_ASM_sgtz:
561 /* slt rd, zero, rs */
562 asm_emit_r(token, (0xC << 2) | 3 | (2 << 12), &ops[0], &zero, &ops[1]);
563 return;
564 case TOK_ASM_bnez:
565 /* bne rs, zero, offset */
566 asm_emit_b(token, 0x63 | (1 << 12), &ops[0], &zero, &ops[1]);
567 return;
568 case TOK_ASM_beqz:
569 /* bne rs, zero, offset */
570 asm_emit_b(token, 0x63 | (0 << 12), &ops[0], &zero, &ops[1]);
571 return;
572 case TOK_ASM_blez:
573 /* bge rs, zero, offset */
574 asm_emit_b(token, 0x63 | (5 << 12), &ops[0], &zero, &ops[1]);
575 return;
576 case TOK_ASM_bgez:
577 /* bge zero, rs, offset */
578 asm_emit_b(token, 0x63 | (5 << 12), &zero, &ops[0], &ops[1]);
579 return;
580 case TOK_ASM_bltz:
581 /* blt rs, zero, offset */
582 asm_emit_b(token, 0x63 | (4 << 12), &ops[0], &zero, &ops[1]);
583 return;
584 case TOK_ASM_bgtz:
585 /* blt zero, rs, offset */
586 asm_emit_b(token, 0x63 | (4 << 12), &zero, &ops[0], &ops[1]);
587 return;
455 588
456 default:589 default:
457 expect("binary instruction");590 expect("binary instruction");
@@ -549,8 +682,23 @@ static void asm_mem_access_opcode(TCCState *s1, int token) · 91 unmodified lines
549 Operand ops[3];682 Operand ops[3];
550 parse_mem_access_operands(s1, &ops[0]);683 parse_mem_access_operands(s1, &ops[0]);
551 684
552 // l{b|h|w|d}[u] rd, imm(rs1); I-format685 /* Pseudoinstruction: inst reg, label
686 * expand to:
687 * auipc reg, 0
688 * inst reg, 0(reg)
689 * And with the proper relocation to label
690 */
691 if (ops[1].type == OP_IM32 && ops[1].e.sym && ops[1].e.sym->type.t & VT_STATIC){
692 ops[1] = ops[0];
693 /* set the offset to zero */
694 ops[2].type = OP_IM12S;
695 ops[2].e.v = 0;
696 /* auipc reg, 0 */
697 asm_emit_u(token, (0x05 << 2) | 3, &ops[0], &ops[2]);
698 }
699
553 switch (token) {700 switch (token) {
701 // l{b|h|w|d}[u] rd, imm(rs1); I-format
554 case TOK_ASM_lb:702 case TOK_ASM_lb:
555 asm_emit_i(token, (0x0 << 2) | 3, &ops[0], &ops[1], &ops[2]);703 asm_emit_i(token, (0x0 << 2) | 3, &ops[0], &ops[1], &ops[2]);
556 return;704 return;
@@ -713,6 +861,19 @@ static void asm_ternary_opcode(TCCState *s1, int token) · 156 unmodified lines
713 case TOK_ASM_bgeu:861 case TOK_ASM_bgeu:
714 asm_emit_b(token, 0x63 | (7 << 12), ops, ops + 1, ops + 2);862 asm_emit_b(token, 0x63 | (7 << 12), ops, ops + 1, ops + 2);
715 return;863 return;
864 /* related pseudoinstructions */
865 case TOK_ASM_bgt:
866 asm_emit_b(token, 0x63 | (4 << 12), ops + 1, ops, ops + 2);
867 return;
868 case TOK_ASM_ble:
869 asm_emit_b(token, 0x63 | (5 << 12), ops + 1, ops, ops + 2);
870 return;
871 case TOK_ASM_bgtu:
872 asm_emit_b(token, 0x63 | (6 << 12), ops + 1, ops, ops + 2);
873 return;
874 case TOK_ASM_bleu:
875 asm_emit_b(token, 0x63 | (7 << 12), ops + 1, ops, ops + 2);
876 return;
716 877
717 /* M extension */878 /* M extension */
718 case TOK_ASM_div:879 case TOK_ASM_div:
@@ -1030,14 +1191,44 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 311 unmodified lines
1030 1191
1031 /* pseudoinstructions */1192 /* pseudoinstructions */
1032 case TOK_ASM_nop:1193 case TOK_ASM_nop:
1194 case TOK_ASM_ret:
1033 asm_nullary_opcode(s1, token);1195 asm_nullary_opcode(s1, token);
1034 return;1196 return;
1035 1197
1198 case TOK_ASM_jr:
1199 case TOK_ASM_call:
1200 case TOK_ASM_tail:
1201 asm_unary_opcode(s1, token);
1202 return;
1203
1036 case TOK_ASM_la:1204 case TOK_ASM_la:
1037 case TOK_ASM_lla:1205 case TOK_ASM_lla:
1206 case TOK_ASM_li:
1207 case TOK_ASM_jump:
1208 case TOK_ASM_seqz:
1209 case TOK_ASM_snez:
1210 case TOK_ASM_sltz:
1211 case TOK_ASM_sgtz:
1212 case TOK_ASM_bnez:
1213 case TOK_ASM_beqz:
1214 case TOK_ASM_blez:
1215 case TOK_ASM_bgez:
1216 case TOK_ASM_bltz:
1217 case TOK_ASM_bgtz:
1218 case TOK_ASM_mv:
1219 case TOK_ASM_not:
1220 case TOK_ASM_neg:
1221 case TOK_ASM_negw:
1038 asm_binary_opcode(s1, token);1222 asm_binary_opcode(s1, token);
1039 return;1223 return;
1040 1224
1225 case TOK_ASM_bgt:
1226 case TOK_ASM_bgtu:
1227 case TOK_ASM_ble:
1228 case TOK_ASM_bleu:
1229 asm_ternary_opcode(s1, token);
1230 return;
1231
1041 default:1232 default:
1042 expect("known instruction");1233 expect("known instruction");
1043 }1234 }
riscv64-tok.h+2−0
@@ -393,6 +393,8 @@ · 392 unmodified lines
393 DEF_ASM(fsd)393 DEF_ASM(fsd)
394 DEF_ASM(fsw)394 DEF_ASM(fsw)
395 DEF_ASM(j)395 DEF_ASM(j)
396 DEF_ASM(jump)
397 DEF_ASM(jr)
396 DEF_ASM(la)398 DEF_ASM(la)
397 DEF_ASM(li)399 DEF_ASM(li)
398 DEF_ASM(lla)400 DEF_ASM(lla)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t