Karoshi MSX Community
06 de Julio de 2021, 12:21:58 am *
Bienvenido(a), Visitante. Por favor, ingresa o regístrate.

Ingresar con nombre de usuario, contraseña y duración de la sesión
Noticias:
 
   Inicio   Ayuda Buscar Ingresar Registrarse  
Páginas: [1] 2
  Imprimir  
Autor Tema: Cross compiler  (Leído 7357 veces)
0 Usuarios y 1 Visitante están viendo este tema.
samsaga2
Karoshi Fan
**
Mensajes: 76


Email
« : 09 de Noviembre de 2011, 05:15:50 pm »

Como me sobra tanto tiempo libre Roll Eyes y siguiendo la moda de abandonar la scene emesexera (o no) he retomado un proyecto que tenía perdido por el disco duro y lo he subido a github:

https://github.com/samsaga2/Z80-IR-Compiler

Me le explico (explicomele para los amigos).

¿Os gustaría tener éste código en basic...

Código:
REM test
10 a = &h1 ' com 1
20 b = &b10: c = 3 : d = a+b+c ' com 2

...compilarlo y obtener...

Código:

        ; main
_main:  ld bc,&h1
        ld [_a],bc
        ld bc,&b10
        ld [_b],bc
        ld bc,3
        ld [_c],bc
        ld de,[_a]
        ld hl,[_b]
        add hl,de
        ld de,hl
        ld hl,[_c]
        add hl,de
        ld bc,hl
        ld [_d],bc
        ret

o este codigo en pseudo-c#

Código:
int test1()
{
    return 0x1;
}

int test2()
{
    return 0b10+3;
}

int test3()
{
    return test1() + test2();
}

int test4()
{
    int a=test1();
    int b=test2();
    int c=a+b;
    return c+test3();
}

...y obtener...

Código:
        ; test1
_test1: ld hl,0x1
        ret

        ; test2
_test2: ld hl,(3+0b10)
        ret

        ; test3
_test3: call _test1
        ld de,hl
        call _test2
        add hl,de
        ret

        ; test4
_test4: call _test1
        ld de,hl
        call _test2
        add hl,de
        push hl
        call _test3
        pop de
        add hl,de
        ret

Pues ahora gracias a meloflipo productions podeis. Bueno, podeis si os interesa programar sin agrumentos, ni condicionales ni bucles ni nada y sólo pudiendo sumar Griel (esto está en pañalísimos). Leer el TODO.txt para haceros un idea de lo que falta, que es todo. Pero la parte más complicada, el register allocator, está hecha (estilo ssa que es la técnica mas avanzada).

Mi idea es hacer una especie de .Net pero con cross-compiling (y sin garbage colector). Soportando un pseudo lenguaje parecido a c# y otro para basic lo más compatible posible con el de msx.

Lo he hecho básicamente para aprender a hacer compiladores. Pero dependiendo de lo que me anime la gente lo continuaré o no.
En línea
aorante
Karoshi Maniac
****
Mensajes: 451


nuTella Power!


WWW Email
« Respuesta #1 : 10 de Noviembre de 2011, 03:00:13 pm »

Me parece muy interesante tu proyecto. 

Creo que ya se hablo de algo parecido en estos foros, relacionado con java.

Yo sugería hacer un lenguaje con una sintaxis similar al java-script (muy parecida a la de java y C#). Creo que hay mucha gente que conoce estos lenguajes y le seria más sencillo meterse a la programación para MSX.

El problema es que debe de ser complicado o costoso, sobre todo si se quiere obtener un resultado optimo. Es una de las razones por las que se trabaja más directamente en assembler que con otros lenguajes como el C.

Por cierto, ¿donde esta el fichero Todo.txt?

Saludos!
En línea

--------------------------------- ------ ----- --- -- -
aorante/303bcn
http://aorante.blogspot.com
http://twitter.com/#!/aorante
http://303bcn.wordpress.com/
--------------------------------- ------ ----- --- -- -
samsaga2
Karoshi Fan
**
Mensajes: 76


Email
« Respuesta #2 : 11 de Noviembre de 2011, 07:57:19 am »

Más que complicado es mucho mucho trabajo.

El TODO.txt está un poco perdido por ahi.. https://github.com/samsaga2/Z80-IR-Compiler/blob/master/IRCompiler/Docs/TODO.txt.

La idea sería tener un cross-compiler para basic y un lenguaje moderno estilo c# ya que no hay nada parecido para msx y ni z80 en general.
En línea
Jos'b
Karoshi Maniac
****
Mensajes: 262


« Respuesta #3 : 11 de Noviembre de 2011, 09:55:08 am »

A mi me parece un proyecto interesante, ojalá podamos ver el resultado final.
En línea
Mortimer
Karoshi Lover
***
Mensajes: 216


WWW
« Respuesta #4 : 11 de Noviembre de 2011, 10:11:36 am »

Tiene muy buena pinta  Shocked!

Yo pensé hacer algo parecido en Java (No sé si será a lo que se refiere aorante), pero más pensado para RAD y bocetos en PC que un compilador fina para Z80. Es decir programabas en Java con unas funciones para acceder a los recursos de un MSX que funcionaría en el emulador (Tomando atajos), pero sin el paso de compilar a Z80 para poder usarse en un máquina real.

En línea
aorante
Karoshi Maniac
****
Mensajes: 451


nuTella Power!


WWW Email
« Respuesta #5 : 11 de Noviembre de 2011, 06:05:55 pm »

Una idea:
Al lenguaje le añadiría unos objetos (creo que similar a como funcionan los widgets de macOS), para acceder el hardware y facilitar la vida al programador.

Te mando un ejemplo de como podría ser.
Espero que te sirva.  Smiley

Muchos podrían ser sustituidos por llamadas a la BIOS, aunque eso implicaría a que el resultado fuera una ROM.

Código:
void prueba()
{
  // definicion de variables
  var data = new Array(100,110,110,100,44,44,32,32);
  byte position;
  byte value;
  byte A; // 8 bits
  int HL; // 16 bits
  boolean trigger=false;
 
  A++; // autoincremento
  A--;
 
  value = sys.msx.gen; //variable de sistema, proporciona el codigo de generacion de MSX
  //value = sys.ram.size;
   
  vdp.screen.setMode(2);   // inicializa el modo de pantalla
  value = vdp.screen.mode; // lee el modo de pantalla 
 
  vdp.sprite.setMode(1);   // inicializa el modo de sprites: 0=8x8; 1=16x16
  vdp.sprite.zoom = false; // activa el modo zoom de los sprites 
 
  vdp.vram.writeBlock(0x3800,data); // escribe un bloque de datos en la VRAM
  vdp.vram.poke(0x1B01,20);         // escribe un byte en la VRAM
  value = vdp.vram.peek(0x1B01);    // lee un byte de la VRAM
 
  // funciones que actuan directamente con la tabla de nombre de patrones
  vdp.tile.set(x,y,value);
  value = vdp.tile.get(x,y);
 
  // funciones para imprimir texto en la pantalla
  // actuan directamente con la tabla de nombre de patrones
  // validas incluso para screen2
  // Nota: la ultima posición se guarda en una variable de sistema
  vdp.locate(x,y);  // base(0)+(y*32)+x con base 5 para sc1 o 10 para sc2
  vdp.print(cadena);
             
  //accede a los registros del vdp
  vdp.set(0,12);
  value = vdp.get(0);
 
  // acceso a los atributos de los sprites
  // idea: funcion para definir sprite
  vdp.sprite.setPlane(0,1);          // asigna un sprite a un plano de pantalla
  vdp.sprite.setPosition(1,100,120); // (num plano, x,y)
  vdp.sprite.setColor(1,15);         // (num plano, color)
  vdp.sprite.visible(1) = false;     // (num plano) posiciona el sprite y=209
                                     // haciendolo oculto   
 
  // acceso al PSG
  psg.channelA.volume = 15;
  psg.channelA.frequency = 1500;
  psg.channelA.tone = true;
  psg.channelA.noise = false;
  // idem para B y C
   
  psg.noise.period = 31;
  psg.envelope.period =1000;
  psg.envelope.wave = 1;
 
  // acceso a la RAM
  sys.ram.poke(1000,10);
  value = sys.ram.peek(1000);
 
  // acceso al teclado
  value = ppi.key(0); //num de fila
 
  // acceso a los joysticks
  position = sys.stick.direction(0); //0 = teclado, 1 = joy A, 2 = joy B
 
  if (sys.stick.triggerA(1)==true)
  {
    trigger = sys.stick.triggerB(1);
  }
   
}
En línea

--------------------------------- ------ ----- --- -- -
aorante/303bcn
http://aorante.blogspot.com
http://twitter.com/#!/aorante
http://303bcn.wordpress.com/
--------------------------------- ------ ----- --- -- -
samsaga2
Karoshi Fan
**
Mensajes: 76


Email
« Respuesta #6 : 12 de Noviembre de 2011, 08:34:07 am »

La idea es incluir soporte asm incrustado y namespaces con lo que se podría hacer una librería externa con todo eso.

Una idea:
Al lenguaje le añadiría unos objetos (creo que similar a como funcionan los widgets de macOS), para acceder el hardware y facilitar la vida al programador.

Te mando un ejemplo de como podría ser.
Espero que te sirva.  Smiley

Muchos podrían ser sustituidos por llamadas a la BIOS, aunque eso implicaría a que el resultado fuera una ROM.

Código:
void prueba()
{
  // definicion de variables
  var data = new Array(100,110,110,100,44,44,32,32);
  byte position;
  byte value;
  byte A; // 8 bits
  int HL; // 16 bits
  boolean trigger=false;
 
  A++; // autoincremento
  A--;
 
  value = sys.msx.gen; //variable de sistema, proporciona el codigo de generacion de MSX
  //value = sys.ram.size;
   
  vdp.screen.setMode(2);   // inicializa el modo de pantalla
  value = vdp.screen.mode; // lee el modo de pantalla 
 
  vdp.sprite.setMode(1);   // inicializa el modo de sprites: 0=8x8; 1=16x16
  vdp.sprite.zoom = false; // activa el modo zoom de los sprites 
 
  vdp.vram.writeBlock(0x3800,data); // escribe un bloque de datos en la VRAM
  vdp.vram.poke(0x1B01,20);         // escribe un byte en la VRAM
  value = vdp.vram.peek(0x1B01);    // lee un byte de la VRAM
 
  // funciones que actuan directamente con la tabla de nombre de patrones
  vdp.tile.set(x,y,value);
  value = vdp.tile.get(x,y);
 
  // funciones para imprimir texto en la pantalla
  // actuan directamente con la tabla de nombre de patrones
  // validas incluso para screen2
  // Nota: la ultima posición se guarda en una variable de sistema
  vdp.locate(x,y);  // base(0)+(y*32)+x con base 5 para sc1 o 10 para sc2
  vdp.print(cadena);
             
  //accede a los registros del vdp
  vdp.set(0,12);
  value = vdp.get(0);
 
  // acceso a los atributos de los sprites
  // idea: funcion para definir sprite
  vdp.sprite.setPlane(0,1);          // asigna un sprite a un plano de pantalla
  vdp.sprite.setPosition(1,100,120); // (num plano, x,y)
  vdp.sprite.setColor(1,15);         // (num plano, color)
  vdp.sprite.visible(1) = false;     // (num plano) posiciona el sprite y=209
                                     // haciendolo oculto   
 
  // acceso al PSG
  psg.channelA.volume = 15;
  psg.channelA.frequency = 1500;
  psg.channelA.tone = true;
  psg.channelA.noise = false;
  // idem para B y C
   
  psg.noise.period = 31;
  psg.envelope.period =1000;
  psg.envelope.wave = 1;
 
  // acceso a la RAM
  sys.ram.poke(1000,10);
  value = sys.ram.peek(1000);
 
  // acceso al teclado
  value = ppi.key(0); //num de fila
 
  // acceso a los joysticks
  position = sys.stick.direction(0); //0 = teclado, 1 = joy A, 2 = joy B
 
  if (sys.stick.triggerA(1)==true)
  {
    trigger = sys.stick.triggerB(1);
  }
   
}
En línea
theNestruo
Karoshi Lover
***
Mensajes: 236


Email
« Respuesta #7 : 13 de Noviembre de 2011, 10:27:25 am »

Yo pensé hacer algo parecido en Java (...), pero más pensado para RAD y bocetos en PC que un compilador fina para Z80. Es decir programabas en Java con unas funciones para acceder a los recursos de un MSX que funcionaría en el emulador (Tomando atajos), (...)
Para RAD y bocetos yo me plantearía utilizar BASIC y emuladores (a los que puedes subir la velocidad de emulación). Las herramientas ya existen y el lenguaje es conocido.
A menos que haya algo más que no esté viendo, ¿lo otro no sería matar moscas a cañonazos?
En línea

theNestruo."Old BASIC programmers never die; they GOSUB but never RETURN."
Mortimer
Karoshi Lover
***
Mensajes: 216


WWW
« Respuesta #8 : 13 de Noviembre de 2011, 07:50:22 pm »

Para RAD y bocetos yo me plantearía utilizar BASIC y emuladores (a los que puedes subir la velocidad de emulación). Las herramientas ya existen y el lenguaje es conocido.
A menos que haya algo más que no esté viendo, ¿lo otro no sería matar moscas a cañonazos?

Pero basic tiene tantas limitaciones de expresividad, que la idea era hacer algo que pudiera aprovechar la potencia de los ordenadores actuales y las facilidades de los lenguajes modernos. Algo con control muy directo a los recursos, como comenta aorante, como si tuvieras un PC con un TMS9918... Pero bueno, al final el proyecto tomó otros derroteros, y ya yo tampoco le veo demasiado sentido.
En línea
samsaga2
Karoshi Fan
**
Mensajes: 76


Email
« Respuesta #9 : 15 de Noviembre de 2011, 09:46:19 am »

De momento voy a concentrarme sólo en la versión pseudo c#. Bastante trabajo me dará como para hacer también un Basic (puede que en futuro). Pero la verdad es que me haría más ilusión meter un forth que un basic (sería y muchísimo más fácil).
En línea
Metalbrain
Karoshi Fan
**
Mensajes: 92


Z80jutsushi


« Respuesta #10 : 15 de Noviembre de 2011, 12:58:36 pm »

La idea sería tener un cross-compiler para basic y un lenguaje moderno estilo c# ya que no hay nada parecido para msx y ni z80 en general.

¿Conoces el ccz80? Creo que es algo similar, aunque con sintaxis mas o menos basada en C:
http://www.telefonica.net/web2/emilioguerrero/ccz80/ccz80sp.html

En línea
samsaga2
Karoshi Fan
**
Mensajes: 76


Email
« Respuesta #11 : 16 de Noviembre de 2011, 12:16:20 pm »

Lo había visto muy por encima pero el código fuente no es libre, sólo soporta spectrum y no soy demasiado fan de su sintaxis.

¿Conoces el ccz80? Creo que es algo similar, aunque con sintaxis mas o menos basada en C:
http://www.telefonica.net/web2/emilioguerrero/ccz80/ccz80sp.html

Voy avanzando ahora tengo soporte de argumentos y estoy haciendo pruebas con condicionales:

Código:
int test1(bool arg0, int arg1)
{
    if(arg0)
        return arg1+arg1;

    return arg1;
}

int test2()
{
    return test1(true, 1)+test1(false, 3);
}

Se compila a:

Código:
        ; test1
        ; arg arg0 in l
        ; arg arg1 in de
_test1: ld a,l
        or a
        jr z $b1
        ld hl,de
        add hl,de
        ret
b1:     ld hl,de
        ret

        ; test2
_test2: ld l,255
        ld de,1
        call _test1
        ld bc,hl
        ld l,0
        ld de,3
        call _test1
        add hl,bc
        ret

El mismo código en el sdcc se queda en:

Código:
                              1 ;--------------------------------------------------------
                              2 ; File Created by SDCC : free open source ANSI-C Compiler
                              3 ; Version 3.0.6 #7037 (Nov 16 2011) (CYGWIN)
                              4 ; This file was generated Wed Nov 16 12:04:29 2011
                              5 ;--------------------------------------------------------
                              6 .module kk
                              7 .optsdcc -mz80
                              8
                              9 ;--------------------------------------------------------
                             10 ; Public variables in this module
                             11 ;--------------------------------------------------------
                             12 .globl _test2
                             13 .globl _test1
                             14 ;--------------------------------------------------------
                             15 ; special function registers
                             16 ;--------------------------------------------------------
                             17 ;--------------------------------------------------------
                             18 ;  ram data
                             19 ;--------------------------------------------------------
                             20 .area _DATA
                             21 ;--------------------------------------------------------
                             22 ; overlayable items in  ram
                             23 ;--------------------------------------------------------
                             24 .area _OVERLAY
                             25 ;--------------------------------------------------------
                             26 ; external initialized ram data
                             27 ;--------------------------------------------------------
                             28 ;--------------------------------------------------------
                             29 ; global & static initialisations
                             30 ;--------------------------------------------------------
                             31 .area _HOME
                             32 .area _GSINIT
                             33 .area _GSFINAL
                             34 .area _GSINIT
                             35 ;--------------------------------------------------------
                             36 ; Home
                             37 ;--------------------------------------------------------
                             38 .area _HOME
                             39 .area _HOME
                             40 ;--------------------------------------------------------
                             41 ; code
                             42 ;--------------------------------------------------------
                             43 .area _CODE
                             44 ;kk.c:5: bool test1(bool arg0, int arg1)
                             45 ; ---------------------------------
                             46 ; Function test1
                             47 ; ---------------------------------
   0000                      48 _test1_start::
   0000                      49 _test1:
   0000 DD E5                50 push ix
   0002 DD 21 00 00          51 ld ix,#0
   0006 DD 39                52 add ix,sp
                             53 ;kk.c:7: if(arg0)
   0008 DD 7E 04             54 ld a,4 (ix)
   000B B7                   55 or a, a
   000C 28 07                56 jr Z,00102$
                             57 ;kk.c:8: return arg1 + arg1;
   000E DD 7E 05             58 ld a,5 (ix)
   0011 87                   59 add a, a
   0012 6F                   60 ld l,a
   0013 18 02                61 jr 00103$
   0015                      62 00102$:
                             63 ;kk.c:10: return true;
   0015 2E FF                64 ld l,#0xFF
   0017                      65 00103$:
   0017 DD E1                66 pop ix
   0019 C9                   67 ret
   001A                      68 _test1_end::
                             69 ;kk.c:13: bool test2()
                             70 ; ---------------------------------
                             71 ; Function test2
                             72 ; ---------------------------------
   001A                      73 _test2_start::
   001A                      74 _test2:
                             75 ;kk.c:15: return test1(true, 1) + test1(false, 3);
   001A 21 01 00             76 ld hl,#0x0001
   001D E5                   77 push hl
   001E 3E FF                78 ld a,#0xFF
   0020 F5                   79 push af
   0021 33                   80 inc sp
   0022 CDr00s00             81 call _test1
   0025 F1                   82 pop af
   0026 33                   83 inc sp
   0027 55                   84 ld d,l
   0028 D5                   85 push de
   0029 21 03 00             86 ld hl,#0x0003
   002C E5                   87 push hl
   002D 3E 00                88 ld a,#0x00
   002F F5                   89 push af
   0030 33                   90 inc sp
   0031 CDr00s00             91 call _test1
   0034 F1                   92 pop af
   0035 33                   93 inc sp
   0036 D1                   94 pop de
   0037 7A                   95 ld a,d
   0038 85                   96 add a, l
   0039 6F                   97 ld l,a
   003A C9                   98 ret
   003B                      99 _test2_end::
                            100 .area _CODE
                            101 .area _CABS

Ops, bug gordo en la linia 59 (¿porqué suma bytes si arg1 es un int?).

Como ves es una mejora importante respecto al sdcc. Pero aún está muy lejos el que sea un compilador usable.


En línea
Metalbrain
Karoshi Fan
**
Mensajes: 92


Z80jutsushi


« Respuesta #12 : 16 de Noviembre de 2011, 03:53:57 pm »

Lo había visto muy por encima pero el código fuente no es libre, sólo soporta spectrum y no soy demasiado fan de su sintaxis.

Lo del código fuente es verdad, pero soporta Spectrum, Amstrad CPC y se supone que también MSX, aunque creo que dicho soporte de MSX está un poco en pañales:

http://ccz80.foroactivo.com/t11-usar-ccz80-para-msx
http://ccz80.foroactivo.com/t53-se-pueden-crear-rom-s-de-msx
En línea
samsaga2
Karoshi Fan
**
Mensajes: 76


Email
« Respuesta #13 : 01 de Diciembre de 2011, 12:15:32 pm »

El primer programa funcional con el compilador:

Código:
namespace Z80
{
void di()
{
asm("di");
}

void ei()
{
asm("ei");
}
}

namespace MSX.Keyboard
{
void disableClick()
{
asm("xor a
    ld (0f3dbh),a");
}

void enableClick()
{
asm("ld a,1
    ld (0f3dbh),a");
}

byte readChar()
{
return asm("call 009fh", "", "byte:a");
}
}

namespace MSX.Screen
{
void setMode(byte mode)
{
asm("call 005fh", "mode:a");
}

void setColor(byte foreground, byte background, byte border)
{
asm("ld (0f3e9h),hl
             ld a,e
             ld (0f3ebh),a
call 0062h",
"foreground:l, background:h, border:e");
}

void fillVRAM(word addr, word len, byte data)
{
asm("call 0056h", "addr:hl, len:bc, data:a");
}

void writeRAM(word addr, byte value)
{
asm("call 0177h", "addr:hl, value:a");
}

void putChar(byte char)
{
asm("call 00a2h", "char:a");
}
}

using MSX;

namespace Program
{
void init()
{
Keyboard.disableClick();
Screen.setMode(1b);
Screen.setColor(15b, 0b, 0b);
}

void start()
{
Z80.di();
init();
while(true)
{
Screen.putChar(Keyboard.readChar());
}
}
}

Se compila a...

Código:
; Z80.di
_Z80_di:
di
ret



; Z80.ei
_Z80_ei:
ei
ret



; MSX.Keyboard.disableClick
_MSX_Keyboard_disableClick:
xor a
ld (0f3dbh),a
ret



; MSX.Keyboard.enableClick
_MSX_Keyboard_enableClick:
ld a,1
ld (0f3dbh),a
ret



; MSX.Keyboard.readChar
_MSX_Keyboard_readChar:
call 009fh
ld l,a
ret



; MSX.Screen.setMode
; arg mode in l
_MSX_Screen_setMode:
ld a,l
call 005fh
ret



; MSX.Screen.setColor
; arg foreground in l
; arg background in h
; arg border in e
_MSX_Screen_setColor:
ld (0f3e9h),hl
ld a,e
ld (0f3ebh),a
call 0062h
ret



; MSX.Screen.fillVRAM
; arg addr in hl
; arg len in de
; arg data in c
_MSX_Screen_fillVRAM:
ld c,e
ld b,d
ld a,c
call 0056h
ret



; MSX.Screen.writeRAM
; arg addr in hl
; arg value in e
_MSX_Screen_writeRAM:
ld a,e
call 0177h
ret



; MSX.Screen.putChar
; arg char in l
_MSX_Screen_putChar:
ld a,l
call 00a2h
ret



; Program.init
_Program_init:
call _MSX_Keyboard_disableClick
ld l,1
call _MSX_Screen_setMode
ld hl,15 + 0 * 256
ld e,0
call _MSX_Screen_setColor
ret



; Program.start
_Program_start:
call _Z80_di
call _Program_init
b1:
call _MSX_Keyboard_readChar
call _MSX_Screen_putChar
jr b1
b2:
ret

Los tres primeros parámetros de las funciones se pasan en los registros hl, de y bc. Además el register allocator minimiza el uso de variables en la pila (que son los dos problemsa principales del sdcc y el hitech-c).

Cuando implemente el inline de funciones el código quedará aún mucho más optimizado. Ya que eliminará calls, rets y loads innecesarios.
En línea
kabish
Karoshi Maniac
****
Mensajes: 470


caspaflims@hotmail.com
« Respuesta #14 : 01 de Diciembre de 2011, 11:04:52 pm »

Muy interesante. Smiley
En línea
Páginas: [1] 2
  Imprimir  
 
Ir a:  

Impulsado por MySQL Impulsado por PHP Powered by SMF 1.1.21 | SMF © 2013, Simple Machines XHTML 1.0 válido! CSS válido!