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/i686.c \
|
||||
$(PACKAGE)-$(VERSION)/src/arch/sparc.c \
|
||||
$(PACKAGE)-$(VERSION)/src/arch/sparc64.c \
|
||||
$(PACKAGE)-$(VERSION)/src/arch/Makefile \
|
||||
$(PACKAGE)-$(VERSION)/src/arch/common.ins \
|
||||
$(PACKAGE)-$(VERSION)/src/arch/i386.h \
|
||||
@ -65,6 +66,7 @@ dist:
|
||||
$(PACKAGE)-$(VERSION)/src/arch/i686.ins \
|
||||
$(PACKAGE)-$(VERSION)/src/arch/i686.reg \
|
||||
$(PACKAGE)-$(VERSION)/src/arch/null.ins \
|
||||
$(PACKAGE)-$(VERSION)/src/arch/sparc.h \
|
||||
$(PACKAGE)-$(VERSION)/src/arch/sparc.ins \
|
||||
$(PACKAGE)-$(VERSION)/src/arch/sparc.reg \
|
||||
$(PACKAGE)-$(VERSION)/src/arch/project.conf \
|
||||
@ -81,6 +83,7 @@ dist:
|
||||
$(PACKAGE)-$(VERSION)/test/i586.S \
|
||||
$(PACKAGE)-$(VERSION)/test/i686.S \
|
||||
$(PACKAGE)-$(VERSION)/test/sparc.S \
|
||||
$(PACKAGE)-$(VERSION)/test/sparc64.S \
|
||||
$(PACKAGE)-$(VERSION)/test/Makefile \
|
||||
$(PACKAGE)-$(VERSION)/test/project.conf \
|
||||
$(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
|
||||
DESTDIR =
|
||||
LIBDIR = $(PREFIX)/lib
|
||||
@ -60,6 +60,13 @@ sparc_LDFLAGS = $(LDFLAGSF) $(LDFLAGS)
|
||||
sparc.so: $(sparc_OBJS)
|
||||
$(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
|
||||
$(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
|
||||
$(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
|
||||
|
||||
sparc64.o: sparc64.c common.ins null.ins sparc.h sparc.ins sparc.reg
|
||||
$(CC) $(sparc64_CFLAGS) -c sparc64.c
|
||||
|
||||
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
|
||||
$(RM) -- $(TARGETS)
|
||||
@ -97,6 +107,8 @@ install: $(TARGETS)
|
||||
$(INSTALL) -m 0644 -- i686.so $(DESTDIR)$(LIBDIR)/asm/arch/i686.so
|
||||
$(MKDIR) $(DESTDIR)$(LIBDIR)/asm/arch
|
||||
$(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:
|
||||
$(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/i386.so
|
||||
@ -105,5 +117,6 @@ uninstall:
|
||||
$(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/i586.so
|
||||
$(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/i686.so
|
||||
$(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/sparc.so
|
||||
$(RM) -- $(DESTDIR)$(LIBDIR)/asm/arch/sparc64.so
|
||||
|
||||
.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
|
||||
cflags_force=-W `pkg-config --cflags libSystem`
|
||||
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]
|
||||
type=plugin
|
||||
@ -50,4 +50,12 @@ sources=sparc.c
|
||||
install=$(LIBDIR)/asm/arch
|
||||
|
||||
[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 */
|
||||
static int _sparc_write(ArchPlugin * plugin, ArchInstruction * instruction,
|
||||
ArchInstructionCall * call);
|
||||
#include "sparc.h"
|
||||
|
||||
|
||||
/* protected */
|
||||
@ -57,225 +56,3 @@ ArchPlugin arch_plugin =
|
||||
_sparc_write,
|
||||
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
|
||||
DESTDIR =
|
||||
BINDIR = $(PREFIX)/bin
|
||||
@ -30,6 +30,9 @@ i686.o_ASFLAGS = $(CPPFLAGSF) $(CPPFLAGS) $(ASFLAGS) -a i686 -f flat
|
||||
sparc.o_OBJS = sparc.o
|
||||
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
|
||||
$(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
|
||||
$(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:
|
||||
$(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
|
||||
$(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
|
||||
dist=Makefile
|
||||
|
||||
@ -49,3 +49,11 @@ sources=sparc.S
|
||||
[sparc.S]
|
||||
asflags=-a sparc -f flat
|
||||
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