mescc: Support 64-bit immediates.
authorJan Nieuwenhuizen <janneke@gnu.org>
Sat, 6 Oct 2018 12:51:57 +0000 (14:51 +0200)
committerJan Nieuwenhuizen <janneke@gnu.org>
Sat, 6 Oct 2018 12:51:57 +0000 (14:51 +0200)
* module/mescc/M1.scm (hex2:address8, hex2:immediate8): New function.
(info->M1): Support 64-bit.
* module/mescc/compile.scm (convert-r0): FIXME!
* module/mescc/x86_64/as.scm (x86_64:value->r, x86_64:r->local,
x86_64:label->arg, x86_64:label->r, x86_64:r+value,
x86_64:r-cmp-value, x86_64:r-long-mem-add, x86_64:r-and): Support
64-bit immediates.
* lib/x86_64-mes/x86_64.M1: Likewise.
* scaffold/tests/17-compare-unsigned-char-le.c: Test it.
* scaffold/tests/17-compare-unsigned-short-le.c: Test it.
* build-aux/check-mescc.sh (tests): Run them.

build-aux/check-mescc.sh
lib/x86_64-mes/x86_64.M1
module/mescc/M1.scm
module/mescc/compile.scm
module/mescc/x86_64/as.scm
module/mescc/x86_64/info.scm
scaffold/tests/17-compare-unsigned-char-le.c [new file with mode: 0644]
scaffold/tests/17-compare-unsigned-long-le.c [new file with mode: 0644]
scaffold/tests/17-compare-unsigned-short-le.c [new file with mode: 0644]
scaffold/tests/a0-call-trunc-int.c [new file with mode: 0644]

index 5884f8f83d4cba62b09100daa80f8ec7573ae896..e2fe6c7f04390d9cfab95748e748ae4be8bdb0bc 100755 (executable)
@@ -78,6 +78,9 @@ t
 17-compare-unsigned-gt
 17-compare-unsigned-le
 17-compare-unsigned-lt
+17-compare-unsigned-char-le
+17-compare-unsigned-short-le
+17-compare-unsigned-long-le
 17-compare-and
 17-compare-or
 17-compare-and-or
@@ -218,9 +221,12 @@ t
 99-readdir
 a0-call-trunc-char
 a0-call-trunc-short
+a0-call-trunc-int
 "
 
 broken="$broken
+17-compare-unsigned-char-le
+17-compare-unsigned-short-le
 66-local-char-array
 "
 
index 99c46402e5dda79b6ee215b0640ec1c3ff20c9d0..ba80c46f0709e76a8084bec340c82cf1eff9a7f3 100644 (file)
@@ -17,8 +17,8 @@
 ### along with GNU Mes.  If not, see <http://www.gnu.org/licenses/>.
 
 # reduced instruction set: rax, rdi (some rcx for shift, rdx for mul, div)
-# 184 instructions
-# TODO: $i64/$0x64 instructions are missing
+# and r10 as i64 immediate helper
+# 202 instructions
 DEFINE add____$i32,%rax 4805
 DEFINE add____$i32,%rbp 4881c5
 DEFINE add____$i32,%rdi 4881c7
@@ -30,6 +30,8 @@ DEFINE add____$i8,%rsp 4883c4
 DEFINE add____$i8,(%rax) 8300
 DEFINE add____$i8,(%rdi) 8307
 DEFINE add____$i8,0x8(%rbp) 8345
+DEFINE add____%r15,(%rax) 4c0138
+DEFINE add____%r15,(%rdi) 4c013f
 DEFINE add____%rax,%rax 4801c0
 DEFINE add____%rbp,%rax 4801e8
 DEFINE add____%rdi,%rax 4801f8
@@ -43,12 +45,16 @@ DEFINE addl___$i8,(%rdi) 8307
 DEFINE addw___$i8,(%rax) 668100
 DEFINE addw___$i8,(%rdi) 668107
 DEFINE and____$i32,%rdi 4881e7
+DEFINE and____%r15,%rax 4c21f8
+DEFINE and____%r15,%rdi 4c21ff
 DEFINE and____%rdi,%rax 4821f8
 DEFINE call32 e8
 DEFINE call___*%rax ffd0
 DEFINE call___*%rdi ffd7
 DEFINE cmp____$i32,%rax 483d
 DEFINE cmp____$i8,%rax 4883f8
+DEFINE cmp____%r15,%rax 4c39f8
+DEFINE cmp____%r15,%rdi 4c39ff
 DEFINE hlt f4
 DEFINE idiv___%rdi 48f7ff
 DEFINE ja32  0f87
@@ -68,17 +74,24 @@ DEFINE lahf 9f
 DEFINE mov____$i32,%rax 48c7c0
 DEFINE mov____$i32,%rdi 48c7c7
 DEFINE mov____$i32,0x8(%rbp) c745
+DEFINE mov____$i64,%r15 49bf
 DEFINE mov____$i64,%rax 48a1
 DEFINE mov____$i64,%rax 48b8
+DEFINE mov____$i64,%rax 48b8
+DEFINE mov____$i64,%rdi 48bf
 DEFINE mov____%al,(%rdi) 8807
 DEFINE mov____%al,0x32(%rbp) 8885
 DEFINE mov____%al,0x8(%rbp) 8845
 DEFINE mov____%ax,(%rdi) 668907
 DEFINE mov____%ax,0x8(%rbp) 668945
+DEFINE mov____%eax,%eax 89c0
+DEFINE mov____%eax,%rax 89c0
 DEFINE mov____%eax,(%rdi) 8907
 DEFINE mov____%eax,0x32(%rbp)  8985
 DEFINE mov____%eax,0x8(%rbp) 8945
 DEFINE mov____%eax,0x8(%rbp) 8945
+DEFINE mov____%edi,%edi 89ff
+DEFINE mov____%edi,%rdi 89ff
 DEFINE mov____%edi,0x32(%rbp) 89bd
 DEFINE mov____%edi,0x8(%rbp) 897d
 DEFINE mov____%esi,%eax 89f0
@@ -145,8 +158,12 @@ DEFINE movzbq_%al,%rax 480fb6c0
 DEFINE movzbq_%dil,%rdi 480fb6ff
 DEFINE movzbq_(%rax),%rax 480fb600
 DEFINE movzbq_(%rdi),%rdi 480fb63f
+DEFINE movzlq_%eax,%rax 89c0
+DEFINE movzlq_%edi,%rdi 89ff
 DEFINE movzlq_(%rax),%rax 8b00
 DEFINE movzlq_(%rdi),%rdi 8b3f
+DEFINE movzwq_%ax,%rax 480fb7c0
+DEFINE movzwq_%di,%rdi 480fb7ff
 DEFINE movzwq_(%rax),%rax 480fb700
 DEFINE movzwq_(%rdi),%rdi 480fb73f
 DEFINE mul____%rdi 48f7e7
@@ -159,6 +176,7 @@ DEFINE pop____%rbp 5d
 DEFINE pop____%rdi 5f
 DEFINE pop____%rdx 5a
 DEFINE push___$i32 68
+DEFINE push___%r15 4157
 DEFINE push___%rax 50
 DEFINE push___%rbp 55
 DEFINE push___%rdi 57
index 7ee083eb3460a4de20efc10bca14c90c39f8d37f..aa76f24992310098ad5f0b4d4dfe30f7390efc00 100644 (file)
@@ -53,6 +53,9 @@
 (define (hex2:address o)
   (string-append "&" o))
 
+(define (hex2:address8 o)
+  (string-append "&" o " %0")) ;; FIXME: 64bit
+
 (define (hex2:offset o)
   (string-append "%" o))
 
   (if hex? (string-append "%0x" (dec->hex o))
       (string-append "%" (number->string o))))
 
+(define (hex2:immediate8 o)
+  (if hex? (string-append "%0x" (dec->hex (modulo o #x100000000))
+                          " %0x" (if (< o 0) "-1"
+                                     (dec->hex (quotient o #x100000000))))
+      (string-append "%" (number->string (dec->hex (modulo o #x100000000)))
+                     " %" (if (< o 0) "-1"
+                              (number->string (dec->hex (quoteint o #x100000000)))))))
+
 (define* (display-join o #:optional (sep ""))
   (let loop ((o o))
     (when (pair? o)
        ((and (pair? o) (keyword? (car o)))
         (pmatch o
           ;; FIXME
-          ((#:address (#:string ,string)) (hex2:address (string->label `(#:string ,string))))
+          ((#:address (#:string ,string))
+           (hex2:address (string->label `(#:string ,string))))
           ((#:address (#:address ,address)) (guard (string? address))
            (hex2:address address))
           ((#:address (#:address ,global)) (guard (global? global))
            (hex2:address (function->string function)))
           ((#:address ,number) (guard (number? number))
            (string-join (map text->M1 (int->bv32 number))))
+
+          ((#:address8 (#:string ,string))
+           (hex2:address8 (string->label `(#:string ,string))))
+          ((#:address8 (#:address ,address)) (guard (string? address))
+           (hex2:address8 address))
+          ((#:address8 (#:address ,global)) (guard (global? global))
+           (hex2:address8 (global->string global)))
+          ((#:address8 ,function) (guard (function? function))
+           (hex2:address8 (function->string function)))
+          ((#:address8 ,number) (guard (number? number))
+           (string-join (map text->M1 (int->bv64 number))))
+
           ((#:string ,string)
            (hex2:address (string->label o)))
-          ((#:address ,address) (guard (string? address)) (hex2:address address))
+
+          ((#:address ,address) (guard (string? address))
+           (hex2:address address))
           ((#:address ,global) (guard (global? global))
            (hex2:address (global->string global)))
+
+          ((#:address8 ,address) (guard (string? address))
+           (hex2:address8 address))
+          ((#:address8 ,global) (guard (global? global))
+           (hex2:address8 (global->string global)))
+
           ((#:offset ,offset) (hex2:offset offset))
           ((#:offset1 ,offset1) (hex2:offset1 offset1))
           ((#:immediate ,immediate) (hex2:immediate immediate))
           ((#:immediate1 ,immediate1) (hex2:immediate1 immediate1))
           ((#:immediate2 ,immediate2) (hex2:immediate2 immediate2))
           ((#:immediate4 ,immediate4) (hex2:immediate4 immediate4))
+          ((#:immediate8 ,immediate8) (hex2:immediate8 immediate8))
           (_ (error "text->M1 no match o" o))))
        ((pair? o) (string-join (map text->M1 o)))))
     (define (write-function o)
index 5afbf6ec0942760fb68f6b5ba94c246cdfcb2fe8..aefa580d2e68f91e0f0ff23964601842dd3b0e21 100644 (file)
         (cond ((and (= size 1) sign)
                (wrap-as (as info 'byte-signed-r)))
               ((= size 1)
-               (wrap-as (as info 'byte-r)))
+               (wrap-as (as info 'byte-r))
+               ;;(wrap-as (as info 'byte-signed-r))
+               )
               ((and (= size 2) sign)
                (wrap-as (as info 'word-signed-r)))
               ((= size 2)
-               (wrap-as (as info 'word-r)))
+               (wrap-as (as info 'word-r))
+               ;;(wrap-as (as info 'word-signed-r))
+               )
               ((and (> reg-size 4) (= size 4) sign)
                (wrap-as (as info 'long-signed-r)))
               ((and (> reg-size 4) (= size 4))
-               (wrap-as (as info 'long-signed-r)))
+               ;; for 17-unsigned-le
+               (wrap-as (as info 'long-signed-r))  ; huh, why not long-r?
+               ;; for a0-call-trunc-int
+               ;;(wrap-as (as info 'long-r))
+               )
               (else '())))))
 
 (define (binop->r info)
index 9e3f525832edc08735228caf12ce564d5ad73a88..ca1982a9eb2bcbbaf0bba0da96395453ce09b5fd 100644 (file)
 (define (x86_64:r->local info n)
   (let ((r (get-r info))
         (n (- 0 (* 8 n))))
-    `(,(if (< (abs n) #x80) `(,(string-append "mov____%" r ",0x8(%rbp)") (#:immediate1 ,n))
+    `(,(if (< (abs n) #x80)
+           `(,(string-append "mov____%" r ",0x8(%rbp)") (#:immediate1 ,n))
            `(,(string-append "mov____%" r ",0x32(%rbp)") (#:immediate ,n))))))
 
 (define (x86_64:value->r info v)
   (or v (error "invalid value: x86_64:value->r: " v))
   (let ((r (get-r info)))
-    `((,(string-append "mov____$i32,%" r) (#:immediate ,v)))))
+    (if (and (>= v 0)
+             (< v #xffffffff))
+     `((,(string-append "mov____$i32,%" r) (#:immediate ,v)))
+     `((,(string-append "mov____$i64,%" r) (#:immediate8 ,v))))))
 
 ;; AMD
 (define (x86_64:ret . rest)
 
 (define (x86_64:label->arg info label i)
   (let ((r0 (list-ref x86_64:registers (1+ i))))
-    `((,(string-append "mov____$i32,%" r0) (#:address ,label))))) ;; FIXME: 64 bits
+    (if (< (label v) #x80000000)
+        `((,(string-append "mov____$i32,%" r0) (#:address ,label)))
+        `((,(string-append "mov____$i64,%" r0) (#:address8 ,label))))))
 
 ;; traditional
 (define (x86_64:r->arg info i)
 (define (x86_64:label->arg info label i)
   `(("push___$i32" (#:address ,label))))
 
+;; FIXME?
+;; (define (x86_64:label->arg info label i)
+;;   `((,(string-append "mov____$i64,%r15") (#:address8 ,label))
+;;     ("push___%r15" (#:address ,label))))
+
 (define (x86_64:r0+r1 info)
   (let ((r1 (get-r1 info))
         (r0 (get-r0 info)))
 (define (x86_64:r-mem-add info v)
   (let ((r (get-r info)))
     `(,(if (< (abs v) #x80) `(,(string-append "add____$i8,(%" r ")") (#:immediate1 ,v))
-           `(,(string-append "add____$i32,(%" r ")") (#:immediate ,v))))))
+           `(,(string-append "add____$i32,(%" r ")") (#:immediate ,v)))))) ;; FIXME 64bit
 
 (define (x86_64:r-byte-mem-add info v)
   (let ((r (get-r info)))
     (let ((n (- 0 (* 8 n))))
       `((,(string-append "mov____%rbp,%" r))
         ,(if (< (abs n) #x80) `(,(string-append "add____$i8,%" r) (#:immediate1 ,n))
-             `(,(string-append "add____$i32,%" r)  (#:immediate ,n)))))))
+             `(,(string-append "add____$i32,%" r)  (#:immediate ,n))))))) ;; FIXME 64bit
 
 (define (x86_64:label->r info label)
   (let ((r (get-r info)))
-    `((,(string-append "mov____$i32,%" r) (#:address ,label)))))
+    `((,(string-append "mov____$i64,%" r) (#:address8 ,label)))))
 
 (define (x86_64:r0->r1 info)
   (let ((r0 (get-r0 info))
   (let ((n (- 0 (* 8 n))))
     `(,(if (and (< (abs n) #x80)
                 (< (abs v) #x80)) `("add____$i8,0x8(%rbp)" (#:immediate1 ,n) (#:immediate1 ,v))
-                `("add____$i32,0x32(%rbp)" (#:immediate ,n) (#:immediate ,v))))))
+                `("add____$i32,0x32(%rbp)" (#:immediate ,n) (#:immediate ,v)))))) ;; FIXME: 64b
 
 (define (x86_64:label-mem-add info label v)
   `(,(if (< (abs v) #x80) `("add____$i8,0x32" (#:address ,label) (#:immediate1 ,v))
-         `("add____$i32,0x32" (#:address ,label) (#:immediate ,v)))))
+         `("add____$i32,0x32" (#:address ,label) (#:immediate ,v))))) ;; FIXME: 64b
 
 (define (x86_64:nop info)
   '(("nop")))
 
 (define (x86_64:r+value info v)
   (let ((r (get-r info)))
-    `(,(if (< (abs v) #x80) `(,(string-append "add____$i8,%" r) (#:immediate1 ,v))
-           `(,(string-append "add____$i32,%" r) (#:immediate ,v))))))
+    (cond ((< (abs v) #x80)
+           `((,(string-append "add____$i8,%" r) (#:immediate1 ,v))))
+          ((< (abs v) #x80000000)
+           `((,(string-append "add____$i32,%" r) (#:immediate ,v))))
+          (else
+           `((,(string-append "mov____$i64,%r15") (#:immediate8 ,v))
+             (,(string-append "add____%r15,%" r)))))))
 
 (define (x86_64:r0->r1-mem info)
   (let ((r0 (get-r0 info))
 
 (define (x86_64:r-cmp-value info v)
   (let ((r (get-r info)))
-    `(,(if (< (abs v) #x80) `(,(string-append "cmp____$i8,%" r) (#:immediate1 ,v))
-           `(,(string-append "cmp____$i32,%" r) (#:immediate ,v))))))
+    (cond ((< (abs v) #x80)
+           `((,(string-append "cmp____$i8,%" r) (#:immediate1 ,v))))
+          ((and (>= v 0)
+                (< v #xffffffff))
+           `((,(string-append "cmp____$i32,%" r) (#:immediate ,v))))
+          (else
+           `(,(string-append "mov____$i64,%r15") (#:immediate8 ,v)
+             ,(string-append "cmp____%r15,%" r))))))
 
 (define (x86_64:push-register info r)
   `((,(string-append "push___%" r))))
 (define (x86_64:r0+value info v)
   (let ((r0 (get-r0 info)))
     `(,(if (< (abs v) #x80) `(,(string-append "add____$i8,%" r0) (#:immediate1 ,v))
-           `(,(string-append "add____$i32,%" r0) (#:immediate ,v))))))
+           `(,(string-append "add____$i32,%" r0) (#:immediate ,v)))))) ; FIXME: 64bit
 
 (define (x86_64:value->r0 info v)
   (let ((r0 (get-r0 info)))
 
 (define (x86_64:r-long-mem-add info v)
   (let ((r (get-r info)))
-    `(,(if (< (abs v) #x80) `(,(string-append "addl___$i8,(%" r ")") (#:immediate1 ,v))
-           `(,(string-append "addl___$i32,(%" r ")") (#:immediate ,v))))))
+    (cond  ((< (abs v) #x80)
+            `((,(string-append "addl___$i8,(%" r ")") (#:immediate1 ,v))))
+           ((and (>= v 0)
+                 (< v #xffffffff))
+            `((,(string-append "addl___$i32,(%" r ")") (#:immediate ,v))))
+           (else
+            `((,(string-append "mov____$i64,%r15") (#:immediate8 ,v))
+              (,(string-append "add____%r15,(%" r ")")))))))
 
 (define (x86_64:byte-r->local+n info id n)
   (let* ((n (+ (- 0 (* 8 id)) n))
 
 (define (x86_64:r-and info v)
   (let ((r (get-r info)))
-    `((,(string-append "and____$i32,%" r) (#:immediate ,v)))))
+    (if (and (>= v 0)
+             (< v #xffffffff))
+        `((,(string-append "and____$i32,%" r) (#:immediate ,v)))
+        `((,(string-append "mov____$i64,%r15") (#:immediate8 ,v))
+          (,(string-append "and____%r15,%" r))))))
 
 (define (x86_64:push-r0 info)
   (let ((r0 (get-r0 info)))
index dd320c889249a5e0ef038be9632bf810c0aba4b2..4133ea8525a2f969053858be4fa61642f3662ddf 100644 (file)
@@ -31,7 +31,7 @@
 (define (x86_64-info)
   (make <info> #:types x86_64:type-alist #:registers x86_64:registers #:instructions x86_64:instructions))
 
-(define x86_64:registers '("rax" "rdi" "rsi" "rdx" "rcx" "r8" "r9"))
+(define x86_64:registers '("rax" "rdi" "rsi" "rdx" "rcx" "r8" "r9" "r10" "r11" "r12" "r13" "r14" "r15"))
 (define x86_64:type-alist
   `(("char" . ,(make-type 'signed 1 #f))
     ("short" . ,(make-type 'signed 2 #f))
diff --git a/scaffold/tests/17-compare-unsigned-char-le.c b/scaffold/tests/17-compare-unsigned-char-le.c
new file mode 100644 (file)
index 0000000..24a4e6f
--- /dev/null
@@ -0,0 +1,30 @@
+/* -*-comment-start: "//";comment-end:""-*-
+ * GNU Mes --- Maxwell Equations of Software
+ * Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
+ *
+ * This file is part of GNU Mes.
+ *
+ * GNU Mes is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * GNU Mes is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Mes.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+int
+main ()
+{
+  unsigned char r = -2;
+  if (r <= -3)
+    return 1;
+  if (r <= (unsigned char)-1)
+    return 0;
+  return 2;
+}
diff --git a/scaffold/tests/17-compare-unsigned-long-le.c b/scaffold/tests/17-compare-unsigned-long-le.c
new file mode 100644 (file)
index 0000000..9c34b2e
--- /dev/null
@@ -0,0 +1,30 @@
+/* -*-comment-start: "//";comment-end:""-*-
+ * GNU Mes --- Maxwell Equations of Software
+ * Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
+ *
+ * This file is part of GNU Mes.
+ *
+ * GNU Mes is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * GNU Mes is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Mes.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+int
+main ()
+{
+  unsigned long r = -2;
+  if (r <= -3)
+    return 1;
+  if (r <= -1)
+    return 0;
+  return 2;
+}
diff --git a/scaffold/tests/17-compare-unsigned-short-le.c b/scaffold/tests/17-compare-unsigned-short-le.c
new file mode 100644 (file)
index 0000000..dead66e
--- /dev/null
@@ -0,0 +1,30 @@
+/* -*-comment-start: "//";comment-end:""-*-
+ * GNU Mes --- Maxwell Equations of Software
+ * Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
+ *
+ * This file is part of GNU Mes.
+ *
+ * GNU Mes is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * GNU Mes is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Mes.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+int
+main ()
+{
+  unsigned short r = -2;
+  if (r <= -3)
+    return 1;
+  if (r <= (unsigned short)-1)
+    return 0;
+  return 2;
+}
diff --git a/scaffold/tests/a0-call-trunc-int.c b/scaffold/tests/a0-call-trunc-int.c
new file mode 100644 (file)
index 0000000..d49b385
--- /dev/null
@@ -0,0 +1,39 @@
+/* -*-comment-start: "//";comment-end:""-*-
+ * GNU Mes --- Maxwell Equations of Software
+ * Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
+ *
+ * This file is part of GNU Mes.
+ *
+ * GNU Mes is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * GNU Mes is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Mes.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libmes.h>
+
+long
+f (unsigned int x)
+{
+  eputs ("x="); eputs (utoa (x)); eputs ("\n");
+  return x;
+}
+
+int
+main ()
+{
+  unsigned long x = -1;
+  x = f (x);
+  eputs ("x="); eputs (ultoa (x)); eputs ("\n");
+  if (x != 0xffffffff)
+    return 1;
+  return 0;
+}