xref: /openbmc/qemu/include/gdbstub/helpers.h (revision 0654c794)
14ea5fe99SAlex Bennée /*
24ea5fe99SAlex Bennée  * gdbstub helpers
34ea5fe99SAlex Bennée  *
44ea5fe99SAlex Bennée  * These are all used by the various frontends and have to be host
54ea5fe99SAlex Bennée  * aware to ensure things are store in target order.
64ea5fe99SAlex Bennée  *
74ea5fe99SAlex Bennée  * Copyright (c) 2022 Linaro Ltd
84ea5fe99SAlex Bennée  *
94ea5fe99SAlex Bennée  * SPDX-License-Identifier: GPL-2.0-or-later
104ea5fe99SAlex Bennée  */
114ea5fe99SAlex Bennée 
124ea5fe99SAlex Bennée #ifndef _GDBSTUB_HELPERS_H_
134ea5fe99SAlex Bennée #define _GDBSTUB_HELPERS_H_
144ea5fe99SAlex Bennée 
1594326e4fSPhilippe Mathieu-Daudé #ifndef COMPILING_PER_TARGET
1694326e4fSPhilippe Mathieu-Daudé #error "gdbstub helpers should only be included by target specific code"
1794326e4fSPhilippe Mathieu-Daudé #endif
1894326e4fSPhilippe Mathieu-Daudé 
19*0654c794SPhilippe Mathieu-Daudé #include "exec/tswap.h"
20*0654c794SPhilippe Mathieu-Daudé #include "cpu-param.h"
214ea5fe99SAlex Bennée 
224ea5fe99SAlex Bennée /*
234ea5fe99SAlex Bennée  * The GDB remote protocol transfers values in target byte order. As
244ea5fe99SAlex Bennée  * the gdbstub may be batching up several register values we always
254ea5fe99SAlex Bennée  * append to the array.
264ea5fe99SAlex Bennée  */
274ea5fe99SAlex Bennée 
gdb_get_reg8(GByteArray * buf,uint8_t val)284ea5fe99SAlex Bennée static inline int gdb_get_reg8(GByteArray *buf, uint8_t val)
294ea5fe99SAlex Bennée {
304ea5fe99SAlex Bennée     g_byte_array_append(buf, &val, 1);
314ea5fe99SAlex Bennée     return 1;
324ea5fe99SAlex Bennée }
334ea5fe99SAlex Bennée 
gdb_get_reg16(GByteArray * buf,uint16_t val)344ea5fe99SAlex Bennée static inline int gdb_get_reg16(GByteArray *buf, uint16_t val)
354ea5fe99SAlex Bennée {
364ea5fe99SAlex Bennée     uint16_t to_word = tswap16(val);
374ea5fe99SAlex Bennée     g_byte_array_append(buf, (uint8_t *) &to_word, 2);
384ea5fe99SAlex Bennée     return 2;
394ea5fe99SAlex Bennée }
404ea5fe99SAlex Bennée 
gdb_get_reg32(GByteArray * buf,uint32_t val)414ea5fe99SAlex Bennée static inline int gdb_get_reg32(GByteArray *buf, uint32_t val)
424ea5fe99SAlex Bennée {
434ea5fe99SAlex Bennée     uint32_t to_long = tswap32(val);
444ea5fe99SAlex Bennée     g_byte_array_append(buf, (uint8_t *) &to_long, 4);
454ea5fe99SAlex Bennée     return 4;
464ea5fe99SAlex Bennée }
474ea5fe99SAlex Bennée 
gdb_get_reg64(GByteArray * buf,uint64_t val)484ea5fe99SAlex Bennée static inline int gdb_get_reg64(GByteArray *buf, uint64_t val)
494ea5fe99SAlex Bennée {
504ea5fe99SAlex Bennée     uint64_t to_quad = tswap64(val);
514ea5fe99SAlex Bennée     g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
524ea5fe99SAlex Bennée     return 8;
534ea5fe99SAlex Bennée }
544ea5fe99SAlex Bennée 
gdb_get_reg128(GByteArray * buf,uint64_t val_hi,uint64_t val_lo)554ea5fe99SAlex Bennée static inline int gdb_get_reg128(GByteArray *buf, uint64_t val_hi,
564ea5fe99SAlex Bennée                                  uint64_t val_lo)
574ea5fe99SAlex Bennée {
584ea5fe99SAlex Bennée     uint64_t to_quad;
594ea5fe99SAlex Bennée #if TARGET_BIG_ENDIAN
604ea5fe99SAlex Bennée     to_quad = tswap64(val_hi);
614ea5fe99SAlex Bennée     g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
624ea5fe99SAlex Bennée     to_quad = tswap64(val_lo);
634ea5fe99SAlex Bennée     g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
644ea5fe99SAlex Bennée #else
654ea5fe99SAlex Bennée     to_quad = tswap64(val_lo);
664ea5fe99SAlex Bennée     g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
674ea5fe99SAlex Bennée     to_quad = tswap64(val_hi);
684ea5fe99SAlex Bennée     g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
694ea5fe99SAlex Bennée #endif
704ea5fe99SAlex Bennée     return 16;
714ea5fe99SAlex Bennée }
724ea5fe99SAlex Bennée 
gdb_get_zeroes(GByteArray * array,size_t len)734ea5fe99SAlex Bennée static inline int gdb_get_zeroes(GByteArray *array, size_t len)
744ea5fe99SAlex Bennée {
754ea5fe99SAlex Bennée     guint oldlen = array->len;
764ea5fe99SAlex Bennée     g_byte_array_set_size(array, oldlen + len);
774ea5fe99SAlex Bennée     memset(array->data + oldlen, 0, len);
784ea5fe99SAlex Bennée 
794ea5fe99SAlex Bennée     return len;
804ea5fe99SAlex Bennée }
814ea5fe99SAlex Bennée 
824ea5fe99SAlex Bennée /**
834ea5fe99SAlex Bennée  * gdb_get_reg_ptr: get pointer to start of last element
844ea5fe99SAlex Bennée  * @len: length of element
854ea5fe99SAlex Bennée  *
864ea5fe99SAlex Bennée  * This is a helper function to extract the pointer to the last
874ea5fe99SAlex Bennée  * element for additional processing. Some front-ends do additional
884ea5fe99SAlex Bennée  * dynamic swapping of the elements based on CPU state.
894ea5fe99SAlex Bennée  */
gdb_get_reg_ptr(GByteArray * buf,int len)904ea5fe99SAlex Bennée static inline uint8_t *gdb_get_reg_ptr(GByteArray *buf, int len)
914ea5fe99SAlex Bennée {
924ea5fe99SAlex Bennée     return buf->data + buf->len - len;
934ea5fe99SAlex Bennée }
944ea5fe99SAlex Bennée 
954ea5fe99SAlex Bennée #if TARGET_LONG_BITS == 64
964ea5fe99SAlex Bennée #define gdb_get_regl(buf, val) gdb_get_reg64(buf, val)
974ea5fe99SAlex Bennée #define ldtul_p(addr) ldq_p(addr)
984ea5fe99SAlex Bennée #else
994ea5fe99SAlex Bennée #define gdb_get_regl(buf, val) gdb_get_reg32(buf, val)
1004ea5fe99SAlex Bennée #define ldtul_p(addr) ldl_p(addr)
1014ea5fe99SAlex Bennée #endif
1024ea5fe99SAlex Bennée 
1034ea5fe99SAlex Bennée #endif /* _GDBSTUB_HELPERS_H_ */
104