commit 8013c0388602bef2e589f867a9bff8fa196247c7
Author:     Roberto E. Vargas Caballero <Roberto E. Vargas Caballero>
AuthorDate: Fri Apr 22 17:14:09 2016 +0200
Commit:     Roberto E. Vargas Caballero <Roberto E. Vargas Caballero>
CommitDate: Fri Apr 22 17:14:09 2016 +0200

    [cc2-qbe] Add conversion between types
    
    After this patch, we can begin to use char and short,
    because they are correctly promoted. It also includes
    conversion between float-float, integer-float and float-integer.

diff --git a/cc2/arch/qbe/arch.h b/cc2/arch/qbe/arch.h
index 683308c..031ec6e 100644
--- a/cc2/arch/qbe/arch.h
+++ b/cc2/arch/qbe/arch.h
@@ -104,4 +104,25 @@ enum asmop {
        ASBORD,
        ASBXORD,
        ASCPLD,
+
+       ASEXTBW,
+       ASUEXTBW,
+       ASEXTBL,
+       ASUEXTBL,
+       ASEXTHW,
+       ASUEXTHW,
+       ASEXTHL,
+       ASUEXTHL,
+       ASEXTWL,
+       ASUEXTWL,
+
+       ASSTOL,
+       ASSTOW,
+       ASDTOL,
+       ASDTOW,
+
+       ASSWTOD,
+       ASSWTOS,
+       ASSLTOD,
+       ASSLTOS
 };
diff --git a/cc2/arch/qbe/cgen.c b/cc2/arch/qbe/cgen.c
index 905a888..300f8dd 100644
--- a/cc2/arch/qbe/cgen.c
+++ b/cc2/arch/qbe/cgen.c
@@ -1,4 +1,5 @@
 
+#include <assert.h>
 #include <stdlib.h>
 
 #include "arch.h"
@@ -135,6 +136,76 @@ load(Node *np)
        return new;
 }
 
+static Node *
+cast(Node *nd, Node *ns)
+{
+       Type *ts, *td;
+       Node *tmp;
+       int op, disint, sisint;
+       extern Type uint32type, int32type;
+
+       if ((ns->flags & (ISTMP|ISCONS)) == 0)
+               ns = nd->left = load(ns);
+       td = &nd->type;
+       ts = &ns->type;
+       disint = (td->flags & INTF) != 0;
+       sisint = (ts->flags & INTF) != 0;
+
+       if (disint && sisint) {
+               if (td->size <= ts->size)
+                       return nd;
+               assert(td->size == 4 || td->size == 8);
+               switch (ts->size) {
+               case 1:
+                       op = (td->size == 4) ? ASEXTBW : ASEXTBL;
+                       break;
+               case 2:
+                       op = (td->size == 4) ? ASEXTHW : ASEXTHL;
+                       break;
+               case 4:
+                       op = ASEXTWL;
+                       break;
+               default:
+                       abort();
+               }
+               op += (td->flags & SIGNF) == 0;
+       } else if (disint) {
+               /* conversion from float to int */
+               switch (ts->size) {
+               case 4:
+                       op = (td->size == 8) ? ASSTOL : ASSTOW;
+                       break;
+               case 8:
+                       op = (td->size == 8) ? ASDTOL : ASDTOW;
+                       break;
+               default:
+                       abort();
+               }
+               /* TODO: Add signess */
+       } else {
+               /* conversion from int to float */
+               switch (ts->size) {
+               case 1:
+               case 2:
+                       tmp = tmpnode(newnode());
+                       tmp->type = (ts->flags&SIGNF) ? int32type : uint32type;
+                       tmp->left = ns;
+                       nd->left = ns = cast(tmp, ns);
+               case 4:
+                       op = (td->size == 8) ? ASSWTOD : ASSWTOS;
+                       break;
+               case 8:
+                       op = (td->size == 8) ? ASSLTOD : ASSLTOS;
+                       break;
+               default:
+                       abort();
+               }
+               /* TODO: Add signess */
+       }
+       code(op, tmpnode(nd), ns, NULL);
+       return nd;
+}
+
 Node *
 cgen(Node *np)
 {
@@ -206,11 +277,13 @@ cgen(Node *np)
        case OBLOOP:
        case OELOOP:
                return NULL;
+       case OCAST:
+               assert(r == NULL);
+               return cast(np, l);
        case OPAR:
        case ONEG:
        case OADDR:
        case OPTR:
-       case OCAST:
        case OINC:
        case ODEC:
                abort();
diff --git a/cc2/arch/qbe/code.c b/cc2/arch/qbe/code.c
index 2ed8ffd..0092576 100644
--- a/cc2/arch/qbe/code.c
+++ b/cc2/arch/qbe/code.c
@@ -9,19 +9,19 @@
 
 #define ADDR_LEN (IDENTSIZ+64)
 
-static void binary(void), load(void), store(void);
+static void binary(void), unary(void), store(void);
 
 static struct opdata {
        void (*fun)(void);
        char *txt;
        char letter;
 } optbl [] = {
-       [ASLDB]   =  {.fun = load,  .txt = "load", .letter = 'b'},
-       [ASLDH]   =  {.fun = load,  .txt = "load", .letter = 'h'},
-       [ASLDW]   =  {.fun = load,  .txt = "load", .letter = 'w'},
-       [ASLDL]   =  {.fun = load,  .txt = "load", .letter = 'l'},
-       [ASLDS]   =  {.fun = load,  .txt = "load", .letter = 's'},
-       [ASLDD]   =  {.fun = load,  .txt = "load", .letter = 'd'},
+       [ASLDB]   =  {.fun = unary,  .txt = "load", .letter = 'b'},
+       [ASLDH]   =  {.fun = unary,  .txt = "load", .letter = 'h'},
+       [ASLDW]   =  {.fun = unary,  .txt = "load", .letter = 'w'},
+       [ASLDL]   =  {.fun = unary,  .txt = "load", .letter = 'l'},
+       [ASLDS]   =  {.fun = unary,  .txt = "load", .letter = 's'},
+       [ASLDD]   =  {.fun = unary,  .txt = "load", .letter = 'd'},
 
        [ASSTB]   =  {.fun = store,  .txt = "store", .letter = 'b'},
        [ASSTH]   =  {.fun = store,  .txt = "store", .letter = 'h'},
@@ -99,6 +99,25 @@ static struct opdata {
        [ASGED]   =  {.fun = binary, .txt = "cged", .letter = 'w'},
        [ASEQD]   =  {.fun = binary, .txt = "ceqd", .letter = 'w'},
        [ASNED]   =  {.fun = binary, .txt = "cned", .letter = 'w'},
+
+       [ASEXTBW] =  {.fun = unary, .txt = "extsb", .letter = 'w'},
+       [ASUEXTBW]=  {.fun = unary, .txt = "extub", .letter = 'w'},
+       [ASEXTBL] =  {.fun = unary, .txt = "extsb", .letter = 'l'},
+       [ASUEXTBL]=  {.fun = unary, .txt = "extub", .letter = 'l'},
+       [ASEXTHW] =  {.fun = unary, .txt = "extsh", .letter = 'w'},
+       [ASUEXTHW]=  {.fun = unary, .txt = "extuh", .letter = 'w'},
+       [ASEXTWL] =  {.fun = unary, .txt = "extsh", .letter = 'l'},
+       [ASUEXTWL]=  {.fun = unary, .txt = "extuh", .letter = 'l'},
+
+       [ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'},
+       [ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'},
+       [ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'},
+       [ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'},
+
+       [ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'},
+       [ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'},
+       [ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'},
+       [ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'},
 };
 
 /*
@@ -354,7 +373,7 @@ store(void)
 }
 
 static void
-load(void)
+unary(void)
 {
        struct opdata *p = &optbl[pc->op];
        char to[ADDR_LEN], from[ADDR_LEN];

Reply via email to