4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-03-01 04:25:27 +08:00
Yuriy Kolerov b99f27c25f arc: libgloss: Prepare for porting to ARCv3
There are 3 families of Synopsys DeisgnWare ARC processors:
ARCompact/ARCv1 (32-bit), ARCv2 (32-bit) and ARCv3 (32-bit
and 64-bit targets). Upstream Newlib supports only ARCv1/2.
This commit prepares ARCv1/2 libgloss port to be reused by
ARCv3 port (except crt* files). Note that __ARC64__ macro
stands for all ARCv3 targets.

Signed-off-by: Yuriy Kolerov <ykolerov@synopsys.com>
2024-08-20 18:24:15 -04:00

190 lines
5.1 KiB
C

/*
* hl_gw.c -- Hostlink gateway, low-level hostlink functions.
*
* Copyright (c) 2024 Synopsys Inc.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*
*/
#include <stdint.h>
#include "hl_gw.h"
#define HL_VERSION 1
/*
* Maximum message size without service information,
* see also HL_PAYLOAD_RESERVED.
*/
#ifndef HL_IOCHUNK
#define HL_IOCHUNK 1024
#endif
/*
* Each syscall argument have 4 bytes of service information in hostlink
* protocol (2 bytes for type and 2 for size). Here we reserve space for
* 32 arguments.
*/
#define HL_PAYLOAD_RESERVED (32 * 4)
/* "No message here" mark. */
#define HL_NOADDRESS 0xFFFFFFFF
/* Hostlink gateway structure. */
struct _hl_hdr {
uint32_t version; /* Current version is 1. */
uint32_t target2host_addr; /* Packet address from target to host. */
uint32_t host2target_addr; /* Packet address from host to target. */
uint32_t buf_addr; /* Address for host to write answer. */
uint32_t payload_size; /* Buffer size without packet header. */
uint32_t options; /* For future use. */
uint32_t break_to_mon_addr; /* For future use. */
} __uncached __packed;
/* Hostlink packet header. */
struct _hl_pkt_hdr {
uint32_t packet_id; /* Packet id. Always set to 1 here. */
uint32_t total_size; /* Size of packet including header. */
uint32_t priority; /* For future use. */
uint32_t type; /* For future use. */
uint32_t checksum; /* For future use. */
} __uncached __packed;
/* Main hostlink structure. */
struct _hl {
volatile struct _hl_hdr hdr; /* General hostlink information. */
/* Start of the hostlink buffer. */
volatile struct _hl_pkt_hdr pkt_hdr;
volatile char payload[HL_IOCHUNK + HL_PAYLOAD_RESERVED];
} __aligned (HL_MAX_DCACHE_LINE) __uncached __packed;
/*
* Main structure. Do not rename because simulator will look for the
* '__HOSTLINK__' symbol.
*/
volatile struct _hl __HOSTLINK__ = {
.hdr = {
.version = 1 ,
.target2host_addr = HL_NOADDRESS
}
};
/* Get hostlink payload pointer. */
volatile __uncached void *
_hl_payload (void)
{
return (volatile __uncached void *) &__HOSTLINK__.payload[0];
}
/* Get hostlink payload size (iochunk + reserved space). */
static uint32_t
_hl_payload_size (void)
{
return sizeof (__HOSTLINK__.payload);
}
/* Get used space size in the payload. */
static uint32_t
_hl_payload_used (volatile __uncached void *p)
{
return (volatile __uncached char *) p
- (volatile __uncached char *) _hl_payload ();
}
/* Fill hostlink packet header. */
static void
_hl_pkt_init (volatile __uncached struct _hl_pkt_hdr *pkt, int size)
{
pkt->packet_id = 1;
pkt->total_size = ALIGN (size, 4) + sizeof (*pkt);
pkt->priority = 0;
pkt->type = 0;
pkt->checksum = 0;
}
/* Get hostlink iochunk size. */
uint32_t
_hl_iochunk_size (void)
{
return HL_IOCHUNK;
}
/* Get free space size in the payload. */
uint32_t
_hl_payload_left (volatile __uncached void *p)
{
return _hl_payload_size () - _hl_payload_used (p);
}
/* Send hostlink packet to the host. */
void
_hl_send (volatile __uncached void *p)
{
volatile __uncached struct _hl_hdr *hdr = &__HOSTLINK__.hdr;
volatile __uncached struct _hl_pkt_hdr *pkt_hdr = &__HOSTLINK__.pkt_hdr;
_hl_pkt_init (pkt_hdr, _hl_payload_used (p));
#if defined (__ARC64__)
/*
* Here we pass only low 4 bytes of the packet address (pkt_hdr).
* The high part of the address is obtained from __HOSTLINK__ address.
*/
hdr->buf_addr = (uintptr_t) pkt_hdr & 0xFFFFFFFF;
#else
hdr->buf_addr = (uint32_t) pkt_hdr;
#endif
hdr->payload_size = _hl_payload_size ();
hdr->host2target_addr = HL_NOADDRESS;
hdr->version = HL_VERSION;
hdr->options = 0;
hdr->break_to_mon_addr = 0;
/* This tells the debugger we have a command.
* It is responsibility of debugger to set this back to HL_NOADDRESS
* after receiving the packet.
* Please note that we don't wait here because some implementations
* use _hl_blockedPeek() function as a signal that we send a messege.
*/
hdr->target2host_addr = hdr->buf_addr;
}
/*
* Wait for host response and return pointer to hostlink payload.
* Symbol _hl_blockedPeek() is used by the simulator as message signal.
*/
volatile __uncached char * __noinline
_hl_blockedPeek (void)
{
while (__HOSTLINK__.hdr.host2target_addr == HL_NOADDRESS)
{
/* TODO: Timeout. */
}
return _hl_payload ();
}
/* Get message from host. */
volatile __uncached char *
_hl_recv (void)
{
return _hl_blockedPeek ();
}
/* Mark hostlink buffer as "No message here". */
void
_hl_delete (void)
{
__HOSTLINK__.hdr.target2host_addr = HL_NOADDRESS;
}