i'm hacking rough iss of processor , wonder if there more efficient way to doing (ideally without resorting unsafe library). (simplified) i'm representing memory by:
type datamem []uint8
a register by:
type register uint16
memory needs in byte sized units , processor works in larger units above. means store data do:
func (m *machine) executest (ins instruction) { // store memory // data store specified in 1 register // address store specified register target_address := m.regbank[ins.dst] src_data := m.regbank[ins.src] ///////// start of annoying section//////// var target_0 uint8 var target_1 uint8 target_0 = src_data & 0x0f target_1 = (src_data & 0xf0)>>8 m.data_mem[target_address ] = target_0 m.data_mem[target_address+1] = target_1 /////////// end of annoying section ///////// m.logger.printf("st address %x, data %x\n",target_address,src_data) }
and on sorts of different data types , transfers.
the annoying thing me know processor go code running on have single load instruction could of above in single transfer. i'd expect c compiler optimise me, without breaking out unsafe library , going straight pointers don't think can around this?
i'm open suggestions including better ways model data memory...
because of type safety of go, there's not can differently here without using unsafe package.
the simplest solution, , performant, conversion on target address:
// convert target address *uint16 srcdata = uint16(0xeeee) *(*uint16)(unsafe.pointer(&datamem[targetaddress])) = srcdata
similarly, option shadow []uint8
slice []uint16
slice pointing same memory region. looks more hairy, , have check offsets , alignment yourself.
datamem16 := (*(*[1<<30 - 1]uint16)(unsafe.pointer(&datamem[0])))[:len(datamem)/2 : len(datamem)/2] datamem16[targetaddress/2] = srcdata
one other option try using builtin copy
move bytes. since copy implemented in assembly compiler, may want (though haven't checked assembly of conversion produces, wash)
copy(datamem[targetaddress:], (*(*[2]uint8)(unsafe.pointer(&srcdata)))[:])
or inline-able function @oneofone shows:
func regtomem(reg uint16) *[2]uint8 { return (*[2]uint8)(unsafe.pointer(®)) } copy(mem[targetaddress:], regtomem(0xffff)[:])
https://play.golang.org/p/0c1uywvuzj
if performance critical, , want use architecture specific instructions, "proper" way implement want directly in assembly, code generated first solution hard beat.
Comments
Post a Comment