shithub: riscv

Download patch

ref: 454d26a0e4f91d03bb8f1f4f3f7dbe56d722deab
parent: fa028a9352309fb1a6f1ee66218742ba5cfd921b
author: aiju <devnull@localhost>
date: Fri May 4 07:07:39 EDT 2018

pc: add $ operator

--- a/sys/man/1/pc
+++ b/sys/man/1/pc
@@ -33,6 +33,9 @@
 .TP
 .B < >= < <= == !=
 .PP
+The \fB$\fR operator performs sign extension. \fIn\fB$\fIx\fR truncates \fIx\fR to \fIn\fR bits and sign extends.
+If \fIn\fR is omitted, it is inferred from the highest set bit (the result is always ≤ 0 in this case).
+.PP
 Variables can be defined using
 .BR = .
 The builtin variable
--- a/sys/src/cmd/pc.y
+++ b/sys/src/cmd/pc.y
@@ -195,6 +195,10 @@
 		else
 			mpassign(b, a);
 		break;
+	case '$':
+		a->b = b->b;
+		mpxtend(b, mptoi(a), a);
+		break;
 	}
 	numdecref(b);
 	return a;
@@ -389,6 +393,7 @@
 %left unary
 %left '*' '/' '%'
 %right LOEXP
+%right '$'
 
 %{
 	int save;
@@ -501,6 +506,7 @@
 	| '-' expr %prec unary { $$ = nummod($2); if($$ != nil) mpsub(mpzero, $$, $$); }
 	| '~' expr %prec unary { $$ = nummod($2); if($$ != nil) mpnot($$, $$); }
 	| '!' expr %prec unary { $$ = nummod($2); if($$ != nil) {itomp(mpcmp($$, mpzero) == 0, $$); $$->b = 0; } }
+	| '$' expr { $$ = nummod($2); if($$ != nil) if($2->sign > 0) mpxtend($2, mpsignif($2), $$); else mpassign($2, $$); }
 	| expr '?' expr ':' expr %prec '?' {
 		if($1 == nil || mpcmp($1, mpzero) != 0){
 			$$ = $3;
@@ -541,6 +547,7 @@
 		if($$ == nil) error("no last result");
 		else numincref($$);
 	}
+	| expr '$' expr { $$ = numbin('$', $1, $3); }
 
 elist: { $$.n = 0; } | elist1
 elist1: expr { $$.x[0] = $1; $$.n = 1; }