Re-introducing support for the sparc64 architecture
This commit is contained in:
parent
8ebf1b07af
commit
fae68e5fd1
3
Makefile
3
Makefile
@ -55,6 +55,7 @@ dist:
|
|||||||
$(PACKAGE)-$(VERSION)/src/arch/i586.c \
|
$(PACKAGE)-$(VERSION)/src/arch/i586.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/arch/i686.c \
|
$(PACKAGE)-$(VERSION)/src/arch/i686.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/arch/sparc.c \
|
$(PACKAGE)-$(VERSION)/src/arch/sparc.c \
|
||||||
|
$(PACKAGE)-$(VERSION)/src/arch/sparc64.c \
|
||||||
$(PACKAGE)-$(VERSION)/src/arch/Makefile \
|
$(PACKAGE)-$(VERSION)/src/arch/Makefile \
|
||||||
$(PACKAGE)-$(VERSION)/src/arch/common.ins \
|
$(PACKAGE)-$(VERSION)/src/arch/common.ins \
|
||||||
$(PACKAGE)-$(VERSION)/src/arch/i386.h \
|
$(PACKAGE)-$(VERSION)/src/arch/i386.h \
|
||||||
@ -65,6 +66,7 @@ dist:
|
|||||||
$(PACKAGE)-$(VERSION)/src/arch/i686.ins \
|
$(PACKAGE)-$(VERSION)/src/arch/i686.ins \
|
||||||
$(PACKAGE)-$(VERSION)/src/arch/i686.reg \
|
$(PACKAGE)-$(VERSION)/src/arch/i686.reg \
|
||||||
$(PACKAGE)-$(VERSION)/src/arch/null.ins \
|
$(PACKAGE)-$(VERSION)/src/arch/null.ins \
|
||||||
|
$(PACKAGE)-$(VERSION)/src/arch/sparc.h \
|
||||||
$(PACKAGE)-$(VERSION)/src/arch/sparc.ins \
|
$(PACKAGE)-$(VERSION)/src/arch/sparc.ins \
|
||||||
$(PACKAGE)-$(VERSION)/src/arch/sparc.reg \
|
$(PACKAGE)-$(VERSION)/src/arch/sparc.reg \
|
||||||
$(PACKAGE)-$(VERSION)/src/arch/project.conf \
|
$(PACKAGE)-$(VERSION)/src/arch/project.conf \
|
||||||
@ -81,6 +83,7 @@ dist:
|
|||||||
$(PACKAGE)-$(VERSION)/test/i586.S \
|
$(PACKAGE)-$(VERSION)/test/i586.S \
|
||||||
$(PACKAGE)-$(VERSION)/test/i686.S \
|
$(PACKAGE)-$(VERSION)/test/i686.S \
|
||||||
$(PACKAGE)-$(VERSION)/test/sparc.S \
|
$(PACKAGE)-$(VERSION)/test/sparc.S \
|
||||||
|
$(PACKAGE)-$(VERSION)/test/sparc64.S \
|
||||||
$(PACKAGE)-$(VERSION)/test/Makefile \
|
$(PACKAGE)-$(VERSION)/test/Makefile \
|
||||||
$(PACKAGE)-$(VERSION)/test/project.conf \
|
$(PACKAGE)-$(VERSION)/test/project.conf \
|
||||||
$(PACKAGE)-$(VERSION)/Makefile \
|
$(PACKAGE)-$(VERSION)/Makefile \
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
TARGETS = i386.so i386_real.so i486.so i586.so i686.so sparc.so
|
TARGETS = i386.so i386_real.so i486.so i586.so i686.so sparc.so sparc64.so
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
DESTDIR =
|
DESTDIR =
|
||||||
LIBDIR = $(PREFIX)/lib
|
LIBDIR = $(PREFIX)/lib
|
||||||
@ -60,6 +60,13 @@ sparc_LDFLAGS = $(LDFLAGSF) $(LDFLAGS)
|
|||||||
sparc.so: $(sparc_OBJS)
|
sparc.so: $(sparc_OBJS)
|
||||||
$(LD) -o sparc.so $(sparc_OBJS) $(sparc_LDFLAGS)
|
$(LD) -o sparc.so $(sparc_OBJS) $(sparc_LDFLAGS)
|
||||||
|
|
||||||
|
sparc64_OBJS = sparc64.o
|
||||||
|
sparc64_CFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(CFLAGSF) $(CFLAGS)
|
||||||
|
sparc64_LDFLAGS = $(LDFLAGSF) $(LDFLAGS)
|
||||||
|
|
||||||
|
sparc64.so: $(sparc64_OBJS)
|
||||||
|
$(LD) -o sparc64.so $(sparc64_OBJS) $(sparc64_LDFLAGS)
|
||||||
|
|
||||||
i386.o: i386.c common.ins null.ins i386.h i386.ins i386.reg
|
i386.o: i386.c common.ins null.ins i386.h i386.ins i386.reg
|
||||||
$(CC) $(i386_CFLAGS) -c i386.c
|
$(CC) $(i386_CFLAGS) -c i386.c
|
||||||
|
|
||||||
@ -75,11 +82,14 @@ i586.o: i586.c common.ins null.ins i386.h i386.ins i386.reg i486.ins i586.ins
|
|||||||
i686.o: i686.c common.ins null.ins i386.h i386.ins i386.reg i486.ins i686.ins i686.reg
|
i686.o: i686.c common.ins null.ins i386.h i386.ins i386.reg i486.ins i686.ins i686.reg
|
||||||
$(CC) $(i686_CFLAGS) -c i686.c
|
$(CC) $(i686_CFLAGS) -c i686.c
|
||||||
|
|
||||||
sparc.o: sparc.c common.ins null.ins sparc.ins sparc.reg
|
sparc.o: sparc.c common.ins null.ins sparc.h sparc.ins sparc.reg
|
||||||
$(CC) $(sparc_CFLAGS) -c sparc.c
|
$(CC) $(sparc_CFLAGS) -c sparc.c
|
||||||
|
|
||||||
|
sparc64.o: sparc64.c common.ins null.ins sparc.h sparc.ins sparc.reg
|
||||||
|
$(CC) $(sparc64_CFLAGS) -c sparc64.c
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) -- $(i386_OBJS) $(i386_real_OBJS) $(i486_OBJS) $(i586_OBJS) $(i686_OBJS) $(sparc_OBJS)
|
$(RM) -- $(i386_OBJS) $(i386_real_OBJS) $(i486_OBJS) $(i586_OBJS) $(i686_OBJS) $(sparc_OBJS) $(sparc64_OBJS)
|
||||||
|
|
||||||
distclean: clean
|
distclean: clean
|
||||||
$(RM) -- $(TARGETS)
|
$(RM) -- $(TARGETS)
|
||||||
@ -97,6 +107,8 @@ install: $(TARGETS)
|
|||||||
$(INSTALL) -m 0644 -- i686.so $(DESTDIR)$(LIBDIR)/asm/arch/i686.so
|
$(INSTALL) -m 0644 -- i686.so $(DESTDIR)$(LIBDIR)/asm/arch/i686.so
|
||||||
$(MKDIR) $(DESTDIR)$(LIBDIR)/asm/arch
|
$(MKDIR) $(DESTDIR)$(LIBDIR)/asm/arch
|
||||||
$(INSTALL) -m 0644 -- sparc.so $(DESTDIR)$(LIBDIR)/asm/arch/sparc.so
|
$(INSTALL) -m 0644 -- sparc.so $(DESTDIR)$(LIBDIR)/asm/arch/sparc.so
|
||||||
|
$(MKDIR) $(DESTDIR)$(LIBDIR)/asm/arch
|
||||||
|
$(INSTALL) -m 0644 -- sparc64.so $(DESTDIR)$(LIBDIR)/asm/arch/sparc64.so
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
$(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/i386.so
|
$(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/i386.so
|
||||||
@ -105,5 +117,6 @@ uninstall:
|
|||||||
$(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/i586.so
|
$(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/i586.so
|
||||||
$(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/i686.so
|
$(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/i686.so
|
||||||
$(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/sparc.so
|
$(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/sparc.so
|
||||||
|
$(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/sparc64.so
|
||||||
|
|
||||||
.PHONY: all clean distclean install uninstall
|
.PHONY: all clean distclean install uninstall
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
targets=i386,i386_real,i486,i586,i686,sparc
|
targets=i386,i386_real,i486,i586,i686,sparc,sparc64
|
||||||
cppflags_force=-I ../../include
|
cppflags_force=-I ../../include
|
||||||
cflags_force=-W `pkg-config --cflags libSystem`
|
cflags_force=-W `pkg-config --cflags libSystem`
|
||||||
cflags=-Wall -fPIC -pedantic
|
cflags=-Wall -fPIC -pedantic
|
||||||
dist=Makefile,common.ins,i386.h,i386.ins,i386.reg,i486.ins,i586.ins,i686.ins,i686.reg,null.ins,sparc.ins,sparc.reg
|
dist=Makefile,common.ins,i386.h,i386.ins,i386.reg,i486.ins,i586.ins,i686.ins,i686.reg,null.ins,sparc.h,sparc.ins,sparc.reg
|
||||||
|
|
||||||
[i386]
|
[i386]
|
||||||
type=plugin
|
type=plugin
|
||||||
@ -50,4 +50,12 @@ sources=sparc.c
|
|||||||
install=$(LIBDIR)/asm/arch
|
install=$(LIBDIR)/asm/arch
|
||||||
|
|
||||||
[sparc.c]
|
[sparc.c]
|
||||||
depends=common.ins,null.ins,sparc.ins,sparc.reg
|
depends=common.ins,null.ins,sparc.h,sparc.ins,sparc.reg
|
||||||
|
|
||||||
|
[sparc64]
|
||||||
|
type=plugin
|
||||||
|
sources=sparc64.c
|
||||||
|
install=$(LIBDIR)/asm/arch
|
||||||
|
|
||||||
|
[sparc64.c]
|
||||||
|
depends=common.ins,null.ins,sparc.h,sparc.ins,sparc.reg
|
||||||
|
227
src/arch/sparc.c
227
src/arch/sparc.c
@ -39,10 +39,9 @@ static ArchInstruction _sparc_instructions[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* prototypes */
|
/* functions */
|
||||||
/* plug-in */
|
/* plug-in */
|
||||||
static int _sparc_write(ArchPlugin * plugin, ArchInstruction * instruction,
|
#include "sparc.h"
|
||||||
ArchInstructionCall * call);
|
|
||||||
|
|
||||||
|
|
||||||
/* protected */
|
/* protected */
|
||||||
@ -57,225 +56,3 @@ ArchPlugin arch_plugin =
|
|||||||
_sparc_write,
|
_sparc_write,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* private */
|
|
||||||
/* functions */
|
|
||||||
/* plug-in */
|
|
||||||
/* sparc_write */
|
|
||||||
static int _write_branch(ArchPlugin * plugin, ArchInstruction * instruction,
|
|
||||||
ArchInstructionCall * call, uint32_t * opcode);
|
|
||||||
static int _write_integer(ArchPlugin * plugin, ArchInstruction * instruction,
|
|
||||||
ArchInstructionCall * call, uint32_t * opcode);
|
|
||||||
static int _write_loadstore(ArchPlugin * plugin, ArchInstruction * instruction,
|
|
||||||
ArchInstructionCall * call, uint32_t * opcode);
|
|
||||||
static int _write_sethi(ArchPlugin * plugin, ArchInstruction * instruction,
|
|
||||||
ArchInstructionCall * call, uint32_t * opcode);
|
|
||||||
|
|
||||||
static int _sparc_write(ArchPlugin * plugin, ArchInstruction * instruction,
|
|
||||||
ArchInstructionCall * call)
|
|
||||||
{
|
|
||||||
uint32_t opcode = instruction->opcode;
|
|
||||||
|
|
||||||
if((opcode & 0xc0000000) == 0xc0000000)
|
|
||||||
{
|
|
||||||
if(_write_loadstore(plugin, instruction, call, &opcode) != 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if((opcode & 0xc1c00000) == 0x01000000)
|
|
||||||
{
|
|
||||||
if(_write_sethi(plugin, instruction, call, &opcode) != 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if((opcode & 0xc0000000) == 0x80000000)
|
|
||||||
{
|
|
||||||
if(_write_integer(plugin, instruction, call, &opcode) != 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if((opcode & 0xc1c00000) == 0x00800000)
|
|
||||||
{
|
|
||||||
if(_write_branch(plugin, instruction, call, &opcode) != 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
opcode = _htob32(opcode);
|
|
||||||
if(fwrite(&opcode, sizeof(opcode), 1, plugin->helper->fp) != 1)
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _write_branch(ArchPlugin * plugin, ArchInstruction * instruction,
|
|
||||||
ArchInstructionCall * call, uint32_t * opcode)
|
|
||||||
{
|
|
||||||
uint32_t disp;
|
|
||||||
|
|
||||||
if(AO_GET_TYPE(instruction->op1) != AOT_IMMEDIATE)
|
|
||||||
return -1;
|
|
||||||
disp = call->operands[0].value.immediate.value;
|
|
||||||
if(call->operands[0].value.immediate.negative)
|
|
||||||
disp = -disp;
|
|
||||||
disp &= (0x003fffff);
|
|
||||||
*opcode |= disp;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _write_integer(ArchPlugin * plugin, ArchInstruction * instruction,
|
|
||||||
ArchInstructionCall * call, uint32_t * opcode)
|
|
||||||
{
|
|
||||||
ArchPluginHelper * helper = plugin->helper;
|
|
||||||
uint32_t rd;
|
|
||||||
uint32_t rs1;
|
|
||||||
uint32_t rs2;
|
|
||||||
char const * name;
|
|
||||||
ArchRegister * ar;
|
|
||||||
|
|
||||||
/* rs1 */
|
|
||||||
if(AO_GET_TYPE(instruction->op1) != AOT_REGISTER)
|
|
||||||
return -1;
|
|
||||||
name = call->operands[0].value._register.name;
|
|
||||||
if((ar = helper->get_register_by_name_size(helper->arch,
|
|
||||||
name, 32)) == NULL)
|
|
||||||
return -1;
|
|
||||||
rs1 = (ar->id << 14);
|
|
||||||
/* rs2 */
|
|
||||||
if(AO_GET_TYPE(instruction->op2) == AOT_REGISTER)
|
|
||||||
{
|
|
||||||
name = call->operands[1].value._register.name;
|
|
||||||
if((ar = helper->get_register_by_name_size(helper->arch,
|
|
||||||
name, 32)) == NULL)
|
|
||||||
return -1;
|
|
||||||
rs2 = ar->id;
|
|
||||||
}
|
|
||||||
else if(AO_GET_TYPE(instruction->op2) == AOT_IMMEDIATE)
|
|
||||||
{
|
|
||||||
rs2 = call->operands[1].value.immediate.value;
|
|
||||||
if(call->operands[1].value.immediate.negative)
|
|
||||||
rs2 = -rs2;
|
|
||||||
rs2 &= 0x00001fff;
|
|
||||||
rs2 |= (1 << 13);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
/* rd */
|
|
||||||
if(AO_GET_TYPE(instruction->op3) != AOT_REGISTER)
|
|
||||||
return -1;
|
|
||||||
name = call->operands[2].value._register.name;
|
|
||||||
if((ar = helper->get_register_by_name_size(helper->arch,
|
|
||||||
name, 32)) == NULL)
|
|
||||||
return -1;
|
|
||||||
rd = (ar->id << 25);
|
|
||||||
*opcode |= (rd | rs1 | rs2);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _write_loadstore(ArchPlugin * plugin, ArchInstruction * instruction,
|
|
||||||
ArchInstructionCall * call, uint32_t * opcode)
|
|
||||||
{
|
|
||||||
ArchPluginHelper * helper = plugin->helper;
|
|
||||||
uint32_t rd;
|
|
||||||
uint32_t rs1;
|
|
||||||
uint32_t rs2;
|
|
||||||
char const * name;
|
|
||||||
ArchRegister * ar;
|
|
||||||
|
|
||||||
if(instruction->opcode & (1 << 21)) /* store instruction */
|
|
||||||
{
|
|
||||||
/* rd */
|
|
||||||
if(AO_GET_TYPE(instruction->op1) != AOT_REGISTER)
|
|
||||||
return -1;
|
|
||||||
name = call->operands[0].value._register.name;
|
|
||||||
if((ar = helper->get_register_by_name_size(helper->arch,
|
|
||||||
name, 32)) == NULL)
|
|
||||||
return -1;
|
|
||||||
rd = (ar->id << 25);
|
|
||||||
/* [rs1 + rs2] */
|
|
||||||
if(AO_GET_TYPE(instruction->op2) == AOT_DREGISTER2)
|
|
||||||
{
|
|
||||||
name = call->operands[1].value.dregister2.name;
|
|
||||||
if((ar = helper->get_register_by_name_size(helper->arch,
|
|
||||||
name, 32)) == NULL)
|
|
||||||
return -1;
|
|
||||||
rs1 = (ar->id << 14);
|
|
||||||
name = call->operands[1].value.dregister2.name2;
|
|
||||||
if((ar = helper->get_register_by_name_size(helper->arch,
|
|
||||||
name, 32)) == NULL)
|
|
||||||
return -1;
|
|
||||||
rs2 = ar->id;
|
|
||||||
}
|
|
||||||
else if(AO_GET_TYPE(instruction->op2) == AOT_DREGISTER)
|
|
||||||
{
|
|
||||||
name = call->operands[1].value.dregister.name;
|
|
||||||
if((ar = helper->get_register_by_name_size(helper->arch,
|
|
||||||
name, 32)) == NULL)
|
|
||||||
return -1;
|
|
||||||
rs1 = (ar->id << 14);
|
|
||||||
rs2 = 0; /* FIXME implement */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* [rs1 + rs2] */
|
|
||||||
if(AO_GET_TYPE(instruction->op1) == AOT_DREGISTER2)
|
|
||||||
{
|
|
||||||
name = call->operands[0].value.dregister2.name;
|
|
||||||
if((ar = helper->get_register_by_name_size(helper->arch,
|
|
||||||
name, 32)) == NULL)
|
|
||||||
return -1;
|
|
||||||
rs1 = (ar->id << 14);
|
|
||||||
name = call->operands[0].value.dregister2.name2;
|
|
||||||
if((ar = helper->get_register_by_name_size(helper->arch,
|
|
||||||
name, 32)) == NULL)
|
|
||||||
return -1;
|
|
||||||
rs2 = ar->id;
|
|
||||||
}
|
|
||||||
else if(AO_GET_TYPE(instruction->op1) == AOT_DREGISTER)
|
|
||||||
{
|
|
||||||
name = call->operands[0].value.dregister.name;
|
|
||||||
if((ar = helper->get_register_by_name_size(helper->arch,
|
|
||||||
name, 32)) == NULL)
|
|
||||||
return -1;
|
|
||||||
rs1 = (ar->id << 14);
|
|
||||||
rs2 = 0; /* FIXME implement */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
/* rd */
|
|
||||||
if(AO_GET_TYPE(instruction->op2) != AOT_REGISTER)
|
|
||||||
return -1;
|
|
||||||
name = call->operands[1].value._register.name;
|
|
||||||
if((ar = helper->get_register_by_name_size(helper->arch,
|
|
||||||
name, 32)) == NULL)
|
|
||||||
return -1;
|
|
||||||
rd = (ar->id << 25);
|
|
||||||
}
|
|
||||||
*opcode |= (rd | rs1 | rs2);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _write_sethi(ArchPlugin * plugin, ArchInstruction * instruction,
|
|
||||||
ArchInstructionCall * call, uint32_t * opcode)
|
|
||||||
{
|
|
||||||
ArchPluginHelper * helper = plugin->helper;
|
|
||||||
uint32_t rd;
|
|
||||||
uint32_t value;
|
|
||||||
char const * name;
|
|
||||||
ArchRegister * ar;
|
|
||||||
|
|
||||||
/* value */
|
|
||||||
if(AO_GET_TYPE(instruction->op1) != AOT_IMMEDIATE)
|
|
||||||
return -1;
|
|
||||||
value = (call->operands[0].value.immediate.value >> 10);
|
|
||||||
/* rd */
|
|
||||||
if(AO_GET_TYPE(instruction->op2) != AOT_REGISTER)
|
|
||||||
return -1;
|
|
||||||
name = call->operands[1].value._register.name;
|
|
||||||
if((ar = helper->get_register_by_name_size(helper->arch,
|
|
||||||
name, 32)) == NULL)
|
|
||||||
return -1;
|
|
||||||
rd = (ar->id << 25);
|
|
||||||
*opcode |= (rd | value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
247
src/arch/sparc.h
Normal file
247
src/arch/sparc.h
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2011 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS Devel as */
|
||||||
|
/* This program 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, version 3 of the License.
|
||||||
|
*
|
||||||
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* sparc */
|
||||||
|
/* private */
|
||||||
|
/* prototypes */
|
||||||
|
/* plug-in */
|
||||||
|
static int _sparc_write(ArchPlugin * plugin, ArchInstruction * instruction,
|
||||||
|
ArchInstructionCall * call);
|
||||||
|
|
||||||
|
|
||||||
|
/* functions */
|
||||||
|
/* plug-in */
|
||||||
|
/* sparc_write */
|
||||||
|
static int _write_branch(ArchInstruction * instruction,
|
||||||
|
ArchInstructionCall * call, uint32_t * opcode);
|
||||||
|
static int _write_integer(ArchPlugin * plugin, ArchInstruction * instruction,
|
||||||
|
ArchInstructionCall * call, uint32_t * opcode);
|
||||||
|
static int _write_loadstore(ArchPlugin * plugin, ArchInstruction * instruction,
|
||||||
|
ArchInstructionCall * call, uint32_t * opcode);
|
||||||
|
static int _write_sethi(ArchPlugin * plugin, ArchInstruction * instruction,
|
||||||
|
ArchInstructionCall * call, uint32_t * opcode);
|
||||||
|
|
||||||
|
static int _sparc_write(ArchPlugin * plugin, ArchInstruction * instruction,
|
||||||
|
ArchInstructionCall * call)
|
||||||
|
{
|
||||||
|
uint32_t opcode = instruction->opcode;
|
||||||
|
|
||||||
|
if((opcode & 0xc0000000) == 0xc0000000)
|
||||||
|
{
|
||||||
|
if(_write_loadstore(plugin, instruction, call, &opcode) != 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if((opcode & 0xc1c00000) == 0x01000000)
|
||||||
|
{
|
||||||
|
if(_write_sethi(plugin, instruction, call, &opcode) != 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if((opcode & 0xc0000000) == 0x80000000)
|
||||||
|
{
|
||||||
|
if(_write_integer(plugin, instruction, call, &opcode) != 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if((opcode & 0xc1c00000) == 0x00800000)
|
||||||
|
{
|
||||||
|
if(_write_branch(instruction, call, &opcode) != 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
opcode = _htob32(opcode);
|
||||||
|
if(fwrite(&opcode, sizeof(opcode), 1, plugin->helper->fp) != 1)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _write_branch(ArchInstruction * instruction,
|
||||||
|
ArchInstructionCall * call, uint32_t * opcode)
|
||||||
|
{
|
||||||
|
uint32_t disp;
|
||||||
|
|
||||||
|
if(AO_GET_TYPE(instruction->op1) != AOT_IMMEDIATE)
|
||||||
|
return -1;
|
||||||
|
disp = call->operands[0].value.immediate.value;
|
||||||
|
if(call->operands[0].value.immediate.negative)
|
||||||
|
disp = -disp;
|
||||||
|
disp &= (0x003fffff);
|
||||||
|
*opcode |= disp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _write_integer(ArchPlugin * plugin, ArchInstruction * instruction,
|
||||||
|
ArchInstructionCall * call, uint32_t * opcode)
|
||||||
|
{
|
||||||
|
ArchPluginHelper * helper = plugin->helper;
|
||||||
|
uint32_t rd;
|
||||||
|
uint32_t rs1;
|
||||||
|
uint32_t rs2;
|
||||||
|
char const * name;
|
||||||
|
ArchRegister * ar;
|
||||||
|
|
||||||
|
/* rs1 */
|
||||||
|
if(AO_GET_TYPE(instruction->op1) != AOT_REGISTER)
|
||||||
|
return -1;
|
||||||
|
name = call->operands[0].value._register.name;
|
||||||
|
if((ar = helper->get_register_by_name_size(helper->arch,
|
||||||
|
name, 32)) == NULL)
|
||||||
|
return -1;
|
||||||
|
rs1 = (ar->id << 14);
|
||||||
|
/* rs2 */
|
||||||
|
if(AO_GET_TYPE(instruction->op2) == AOT_REGISTER)
|
||||||
|
{
|
||||||
|
name = call->operands[1].value._register.name;
|
||||||
|
if((ar = helper->get_register_by_name_size(helper->arch,
|
||||||
|
name, 32)) == NULL)
|
||||||
|
return -1;
|
||||||
|
rs2 = ar->id;
|
||||||
|
}
|
||||||
|
else if(AO_GET_TYPE(instruction->op2) == AOT_IMMEDIATE)
|
||||||
|
{
|
||||||
|
rs2 = call->operands[1].value.immediate.value;
|
||||||
|
if(call->operands[1].value.immediate.negative)
|
||||||
|
rs2 = -rs2;
|
||||||
|
rs2 &= 0x00001fff;
|
||||||
|
rs2 |= (1 << 13);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
/* rd */
|
||||||
|
if(AO_GET_TYPE(instruction->op3) != AOT_REGISTER)
|
||||||
|
return -1;
|
||||||
|
name = call->operands[2].value._register.name;
|
||||||
|
if((ar = helper->get_register_by_name_size(helper->arch,
|
||||||
|
name, 32)) == NULL)
|
||||||
|
return -1;
|
||||||
|
rd = (ar->id << 25);
|
||||||
|
*opcode |= (rd | rs1 | rs2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _write_loadstore(ArchPlugin * plugin, ArchInstruction * instruction,
|
||||||
|
ArchInstructionCall * call, uint32_t * opcode)
|
||||||
|
{
|
||||||
|
ArchPluginHelper * helper = plugin->helper;
|
||||||
|
uint32_t rd;
|
||||||
|
uint32_t rs1;
|
||||||
|
uint32_t rs2;
|
||||||
|
char const * name;
|
||||||
|
ArchRegister * ar;
|
||||||
|
|
||||||
|
if(instruction->opcode & (1 << 21)) /* store instruction */
|
||||||
|
{
|
||||||
|
/* rd */
|
||||||
|
if(AO_GET_TYPE(instruction->op1) != AOT_REGISTER)
|
||||||
|
return -1;
|
||||||
|
name = call->operands[0].value._register.name;
|
||||||
|
if((ar = helper->get_register_by_name_size(helper->arch,
|
||||||
|
name, 32)) == NULL)
|
||||||
|
return -1;
|
||||||
|
rd = (ar->id << 25);
|
||||||
|
/* [rs1 + rs2] */
|
||||||
|
if(AO_GET_TYPE(instruction->op2) == AOT_DREGISTER2)
|
||||||
|
{
|
||||||
|
name = call->operands[1].value.dregister2.name;
|
||||||
|
if((ar = helper->get_register_by_name_size(helper->arch,
|
||||||
|
name, 32)) == NULL)
|
||||||
|
return -1;
|
||||||
|
rs1 = (ar->id << 14);
|
||||||
|
name = call->operands[1].value.dregister2.name2;
|
||||||
|
if((ar = helper->get_register_by_name_size(helper->arch,
|
||||||
|
name, 32)) == NULL)
|
||||||
|
return -1;
|
||||||
|
rs2 = ar->id;
|
||||||
|
}
|
||||||
|
else if(AO_GET_TYPE(instruction->op2) == AOT_DREGISTER)
|
||||||
|
{
|
||||||
|
name = call->operands[1].value.dregister.name;
|
||||||
|
if((ar = helper->get_register_by_name_size(helper->arch,
|
||||||
|
name, 32)) == NULL)
|
||||||
|
return -1;
|
||||||
|
rs1 = (ar->id << 14);
|
||||||
|
rs2 = 0; /* FIXME implement */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* [rs1 + rs2] */
|
||||||
|
if(AO_GET_TYPE(instruction->op1) == AOT_DREGISTER2)
|
||||||
|
{
|
||||||
|
name = call->operands[0].value.dregister2.name;
|
||||||
|
if((ar = helper->get_register_by_name_size(helper->arch,
|
||||||
|
name, 32)) == NULL)
|
||||||
|
return -1;
|
||||||
|
rs1 = (ar->id << 14);
|
||||||
|
name = call->operands[0].value.dregister2.name2;
|
||||||
|
if((ar = helper->get_register_by_name_size(helper->arch,
|
||||||
|
name, 32)) == NULL)
|
||||||
|
return -1;
|
||||||
|
rs2 = ar->id;
|
||||||
|
}
|
||||||
|
else if(AO_GET_TYPE(instruction->op1) == AOT_DREGISTER)
|
||||||
|
{
|
||||||
|
name = call->operands[0].value.dregister.name;
|
||||||
|
if((ar = helper->get_register_by_name_size(helper->arch,
|
||||||
|
name, 32)) == NULL)
|
||||||
|
return -1;
|
||||||
|
rs1 = (ar->id << 14);
|
||||||
|
rs2 = 0; /* FIXME implement */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
/* rd */
|
||||||
|
if(AO_GET_TYPE(instruction->op2) != AOT_REGISTER)
|
||||||
|
return -1;
|
||||||
|
name = call->operands[1].value._register.name;
|
||||||
|
if((ar = helper->get_register_by_name_size(helper->arch,
|
||||||
|
name, 32)) == NULL)
|
||||||
|
return -1;
|
||||||
|
rd = (ar->id << 25);
|
||||||
|
}
|
||||||
|
*opcode |= (rd | rs1 | rs2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _write_sethi(ArchPlugin * plugin, ArchInstruction * instruction,
|
||||||
|
ArchInstructionCall * call, uint32_t * opcode)
|
||||||
|
{
|
||||||
|
ArchPluginHelper * helper = plugin->helper;
|
||||||
|
uint32_t rd;
|
||||||
|
uint32_t value;
|
||||||
|
char const * name;
|
||||||
|
ArchRegister * ar;
|
||||||
|
|
||||||
|
/* value */
|
||||||
|
if(AO_GET_TYPE(instruction->op1) != AOT_IMMEDIATE)
|
||||||
|
return -1;
|
||||||
|
value = (call->operands[0].value.immediate.value >> 10);
|
||||||
|
/* rd */
|
||||||
|
if(AO_GET_TYPE(instruction->op2) != AOT_REGISTER)
|
||||||
|
return -1;
|
||||||
|
name = call->operands[1].value._register.name;
|
||||||
|
if((ar = helper->get_register_by_name_size(helper->arch,
|
||||||
|
name, 32)) == NULL)
|
||||||
|
return -1;
|
||||||
|
rd = (ar->id << 25);
|
||||||
|
*opcode |= (rd | value);
|
||||||
|
return 0;
|
||||||
|
}
|
58
src/arch/sparc64.c
Normal file
58
src/arch/sparc64.c
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
/* Copyright (c) 2011 Pierre Pronchery <khorben@defora.org> */
|
||||||
|
/* This file is part of DeforaOS Devel as */
|
||||||
|
/* This program 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, version 3 of the License.
|
||||||
|
*
|
||||||
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "Asm.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* sparc64 */
|
||||||
|
/* private */
|
||||||
|
/* variables */
|
||||||
|
static ArchDescription _sparc64_description =
|
||||||
|
{ "elf", ARCH_ENDIAN_BIG, 32, 32 };
|
||||||
|
|
||||||
|
#define REG(name, size, id) { "" # name, size, id },
|
||||||
|
static ArchRegister _sparc64_registers[] =
|
||||||
|
{
|
||||||
|
#include "sparc.reg"
|
||||||
|
{ NULL, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static ArchInstruction _sparc64_instructions[] =
|
||||||
|
{
|
||||||
|
#include "sparc.ins"
|
||||||
|
#include "common.ins"
|
||||||
|
#include "null.ins"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* functions */
|
||||||
|
#include "sparc.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* protected */
|
||||||
|
/* variables */
|
||||||
|
ArchPlugin arch_plugin =
|
||||||
|
{
|
||||||
|
NULL,
|
||||||
|
"sparc64",
|
||||||
|
&_sparc64_description,
|
||||||
|
_sparc64_registers,
|
||||||
|
_sparc64_instructions,
|
||||||
|
_sparc_write,
|
||||||
|
NULL
|
||||||
|
};
|
@ -1,4 +1,4 @@
|
|||||||
TARGETS = i386.o i386_real.o i486.o i586.o i686.o sparc.o
|
TARGETS = i386.o i386_real.o i486.o i586.o i686.o sparc.o sparc64.o
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
DESTDIR =
|
DESTDIR =
|
||||||
BINDIR = $(PREFIX)/bin
|
BINDIR = $(PREFIX)/bin
|
||||||
@ -30,6 +30,9 @@ i686.o_ASFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(ASFLAGS) -a i686 -f flat
|
|||||||
sparc.o_OBJS = sparc.o
|
sparc.o_OBJS = sparc.o
|
||||||
sparc.o_ASFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(ASFLAGS) -a sparc -f flat
|
sparc.o_ASFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(ASFLAGS) -a sparc -f flat
|
||||||
|
|
||||||
|
sparc64.o_OBJS = sparc64.o
|
||||||
|
sparc64.o_ASFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(ASFLAGS) -a sparc64 -f flat
|
||||||
|
|
||||||
i386.o: i386.S ../src/asm
|
i386.o: i386.S ../src/asm
|
||||||
$(AS) $(i386.o_ASFLAGS) -o i386.o i386.S
|
$(AS) $(i386.o_ASFLAGS) -o i386.o i386.S
|
||||||
|
|
||||||
@ -48,8 +51,11 @@ i686.o: i686.S ../src/asm
|
|||||||
sparc.o: sparc.S ../src/asm
|
sparc.o: sparc.S ../src/asm
|
||||||
$(AS) $(sparc.o_ASFLAGS) -o sparc.o sparc.S
|
$(AS) $(sparc.o_ASFLAGS) -o sparc.o sparc.S
|
||||||
|
|
||||||
|
sparc64.o: sparc64.S ../src/asm
|
||||||
|
$(AS) $(sparc64.o_ASFLAGS) -o sparc64.o sparc64.S
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) -- $(i386.o_OBJS) $(i386_real.o_OBJS) $(i486.o_OBJS) $(i586.o_OBJS) $(i686.o_OBJS) $(sparc.o_OBJS)
|
$(RM) -- $(i386.o_OBJS) $(i386_real.o_OBJS) $(i486.o_OBJS) $(i586.o_OBJS) $(i686.o_OBJS) $(sparc.o_OBJS) $(sparc64.o_OBJS)
|
||||||
|
|
||||||
distclean: clean
|
distclean: clean
|
||||||
$(RM) -- $(TARGETS)
|
$(RM) -- $(TARGETS)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
targets=i386.o,i386_real.o,i486.o,i586.o,i686.o,sparc.o
|
targets=i386.o,i386_real.o,i486.o,i586.o,i686.o,sparc.o,sparc64.o
|
||||||
as=../src/asm
|
as=../src/asm
|
||||||
dist=Makefile
|
dist=Makefile
|
||||||
|
|
||||||
@ -49,3 +49,11 @@ sources=sparc.S
|
|||||||
[sparc.S]
|
[sparc.S]
|
||||||
asflags=-a sparc -f flat
|
asflags=-a sparc -f flat
|
||||||
depends=../src/asm
|
depends=../src/asm
|
||||||
|
|
||||||
|
[sparc64.o]
|
||||||
|
type=object
|
||||||
|
sources=sparc64.S
|
||||||
|
|
||||||
|
[sparc64.S]
|
||||||
|
asflags=-a sparc64 -f flat
|
||||||
|
depends=../src/asm
|
||||||
|
79
test/sparc64.S
Normal file
79
test/sparc64.S
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
.text
|
||||||
|
ldd [%r4 + %r7], %r11 /* 0xd6190007 */
|
||||||
|
ldub [%r23], %r19 /* 0xe60dc000 */
|
||||||
|
sub %r16, %r26, %r27 /* 0xb624001a */
|
||||||
|
smulcc %r29, -$23, %r19 /* 0xa6df7fe9 */
|
||||||
|
|
||||||
|
add %r16, %r26, %r27
|
||||||
|
add %r29, -$23, %r19
|
||||||
|
addcc %r16, %r26, %r27
|
||||||
|
addcc %r29, -$23, %r19
|
||||||
|
and %r16, %r26, %r27
|
||||||
|
and %r29, -$23, %r19
|
||||||
|
andcc %r16, %r26, %r27
|
||||||
|
andcc %r29, -$23, %r19
|
||||||
|
andn %r16, %r26, %r27
|
||||||
|
andn %r29, -$23, %r19
|
||||||
|
andncc %r16, %r26, %r27
|
||||||
|
andncc %r29, -$23, %r19
|
||||||
|
ba $0x3
|
||||||
|
be $0x3
|
||||||
|
bg $0x3
|
||||||
|
bge $0x3
|
||||||
|
bl $0x3
|
||||||
|
ble $0x3
|
||||||
|
bne $0x3 /* 0x12800003 */
|
||||||
|
bz $0x3
|
||||||
|
ld [%r4 + %r7], %r11
|
||||||
|
ld [%r23], %r19
|
||||||
|
ldd [%r4 + %r7], %r11
|
||||||
|
ldd [%r23], %r19
|
||||||
|
ldsb [%r4 + %r7], %r11
|
||||||
|
ldsb [%r23], %r19
|
||||||
|
ldsh [%r4 + %r7], %r11
|
||||||
|
ldsh [%r23], %r19
|
||||||
|
ldub [%r4 + %r7], %r11
|
||||||
|
ldub [%r23], %r19
|
||||||
|
lduh [%r4 + %r7], %r11
|
||||||
|
lduh [%r23], %r19
|
||||||
|
or %r16, %r26, %r27
|
||||||
|
or %r29, -$23, %r19
|
||||||
|
orcc %r16, %r26, %r27
|
||||||
|
orcc %r29, -$23, %r19
|
||||||
|
orn %r16, %r26, %r27
|
||||||
|
orn %r29, -$23, %r19
|
||||||
|
orncc %r16, %r26, %r27
|
||||||
|
orncc %r29, -$23, %r19
|
||||||
|
sdiv %r16, %r26, %r27
|
||||||
|
sdiv %r29, -$23, %r19
|
||||||
|
sdivcc %r16, %r26, %r27
|
||||||
|
sdivcc %r29, -$23, %r19
|
||||||
|
sethi $0x87654321, %r2 /* 0x0521d950 */
|
||||||
|
smul %r16, %r26, %r27
|
||||||
|
smul %r29, -$23, %r19
|
||||||
|
smulcc %r16, %r26, %r27
|
||||||
|
smulcc %r29, -$23, %r19
|
||||||
|
st %r11, [%r4 + %r7]
|
||||||
|
st %r19, [%r23]
|
||||||
|
stb %r11, [%r4 + %r7]
|
||||||
|
stb %r19, [%r23]
|
||||||
|
std %r11, [%r4 + %r7]
|
||||||
|
std %r19, [%r23]
|
||||||
|
sth %r11, [%r4 + %r7]
|
||||||
|
sth %r19, [%r23]
|
||||||
|
udiv %r16, %r26, %r27
|
||||||
|
udiv %r29, -$23, %r19
|
||||||
|
udivcc %r16, %r26, %r27
|
||||||
|
udivcc %r29, -$23, %r19
|
||||||
|
umul %r16, %r26, %r27
|
||||||
|
umul %r29, -$23, %r19
|
||||||
|
umulcc %r16, %r26, %r27
|
||||||
|
umulcc %r29, -$23, %r19
|
||||||
|
xnor %r16, %r26, %r27
|
||||||
|
xnor %r29, -$23, %r19
|
||||||
|
xnorcc %r16, %r26, %r27
|
||||||
|
xnorcc %r29, -$23, %r19
|
||||||
|
xor %r16, %r26, %r27
|
||||||
|
xor %r29, -$23, %r19
|
||||||
|
xorcc %r16, %r26, %r27
|
||||||
|
xorcc %r29, -$23, %r19
|
Loading…
Reference in New Issue
Block a user