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
152152 asm_emit_opcode((0x1C << 2) | 3 | (0x105 << 20));
153153 return;
154154
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+
155161 /* C extension */
156162 case TOK_ASM_c_ebreak:
157163 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
265271 {
266272 uint32_t opcode = (0x1C << 2) | 3 | (2 << 12);
267273 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};
269276
270277 parse_operands(s1, &op, 1);
271278 /* 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
291298 case TOK_ASM_rdinstreth:
292299 asm_emit_opcode(opcode | (0xC82 << 20) | ENCODE_RD(op.reg));
293300 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+
294321 /* C extension */
295322 case TOK_ASM_c_j:
296323 asm_emit_cj(token, 1 | (5 << 13), &op);
@@ -299,10 +326,10 @@ static void asm_unary_opcode(TCCState *s1, int token) · 2 unmodified lines
299326 asm_emit_cj(token, 1 | (1 << 13), &op);
300327 return;
301328 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);
303330 return;
304331 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);
306333 return;
307334 default:
308335 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
331358
332359 static void asm_binary_opcode(TCCState* s1, int token)
333360 {
361+ static const Operand zero = {.type = OP_REG, .reg = 0};
362+ Operand imm = {.type = OP_IM12S, .e = {.v = 0}};
334363 Operand ops[2];
335364 parse_operands(s1, &ops[0], 2);
336365
@@ -452,6 +481,110 @@ static void asm_binary_opcode(TCCState* s1, int token) · 115 unmodified lines
452481 /* addi rd, rd, 0 */
453482 asm_emit_i(token, 3 | (4 << 2), ops, ops, ops + 1);
454483 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;
455588
456589 default:
457590 expect("binary instruction");
@@ -549,8 +682,23 @@ static void asm_mem_access_opcode(TCCState *s1, int token) · 91 unmodified lines
549682 Operand ops[3];
550683 parse_mem_access_operands(s1, &ops[0]);
551684
552− // l{b|h|w|d}[u] rd, imm(rs1); I-format
685+ /* 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+
553700 switch (token) {
701+ // l{b|h|w|d}[u] rd, imm(rs1); I-format
554702 case TOK_ASM_lb:
555703 asm_emit_i(token, (0x0 << 2) | 3, &ops[0], &ops[1], &ops[2]);
556704 return;
@@ -713,6 +861,19 @@ static void asm_ternary_opcode(TCCState *s1, int token) · 156 unmodified lines
713861 case TOK_ASM_bgeu:
714862 asm_emit_b(token, 0x63 | (7 << 12), ops, ops + 1, ops + 2);
715863 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;
716877
717878 /* M extension */
718879 case TOK_ASM_div:
@@ -1030,14 +1191,44 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 311 unmodified lines
10301191
10311192 /* pseudoinstructions */
10321193 case TOK_ASM_nop:
1194+ case TOK_ASM_ret:
10331195 asm_nullary_opcode(s1, token);
10341196 return;
10351197
1198+ case TOK_ASM_jr:
1199+ case TOK_ASM_call:
1200+ case TOK_ASM_tail:
1201+ asm_unary_opcode(s1, token);
1202+ return;
1203+
10361204 case TOK_ASM_la:
10371205 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:
10381222 asm_binary_opcode(s1, token);
10391223 return;
10401224
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+
10411232 default:
10421233 expect("known instruction");
10431234 }
riscv64-tok.h+2−0
@@ -393,6 +393,8 @@ · 392 unmodified lines
393393 DEF_ASM(fsd)
394394 DEF_ASM(fsw)
395395 DEF_ASM(j)
396+ DEF_ASM(jump)
397+ DEF_ASM(jr)
396398 DEF_ASM(la)
397399 DEF_ASM(li)
398400 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