chadjoan

An lm32 union ab user

Aug 1st, 2020 (edited)
79
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /// Alias for the 64-bit integer used in `SneakyString`.
  2. /// This can be used outside of `SneakyString` to document whenever the integer
  3. /// is actually being used to represent a `string`'s {ptr,len} component
  4. /// so that gcc-lm32 will enregister it when passed as a function argument.
  5. alias string_u64 = ulong;
  6.  
  7. /// This union will behave like a `string`. But it's also a 64-bit integer,
  8. /// so there's some chance it will pass in registers. Best of luck!
  9. union SneakyString
  10. {
  11.     string_u64  u64;
  12.     string      str;
  13.     static assert(string_u64.sizeof == string.sizeof); // safety.
  14.     alias str this; // Make it behave like 'string' all the time.
  15.  
  16.     this(string_u64  toDecode) { this.u64 = toDecode; }
  17.     this(string      toWrap)   { this.str = toWrap; }
  18.  
  19.     // For things like "SneakyString p; p = someArg;"
  20.     typeof(this) opAssign(string_u64  toDecode) {
  21.         this.u64 = toDecode;
  22.         return this;
  23.     }
  24.  
  25.     // For things like 'SneakyString p; p = "hello";'
  26.     typeof(this) opAssign(string  toWrap) {
  27.         this.str = toWrap;
  28.         return this;
  29.     }
  30.  
  31.     // Define casting to its integer form.
  32.     string_u64 opCast(T : string_u64)() { return this.u64; }
  33.  
  34.     // Define casting to its string form.
  35.     string opCast(T : string)() { return this.str; }
  36. }
  37.  
  38.  
  39. void call_it()
  40. {
  41.     write_to_host_SL01(SneakyString("hello world!\n"));
  42.     write_to_host_SL02(SneakyString("hello world!\n").u64);
  43. }
  44.  
  45. // If you're really lucky, it will take a hint from the 64-bit ulong in the
  46. // union and just pass this union in registers.
  47. //
  48. // That way, you could just use `SneakyString` as a parameter (and perhaps
  49. // even variable) everywhere. If it really does enregister this thing, you
  50. // wouldn't have to worry about the semantics of the 64-bit integer, because
  51. // the "alias str this" statement in the union will make it behave like
  52. // a `string` wherever possible.
  53. //
  54. // Here's an example to compile to see if it provides acceptable assembly code:
  55. //
  56. void write_to_host_SL01(SneakyString msg) {
  57.     // a fixed address to get bytes to the host via usb
  58.     char *usb_slave = cast(char*)BaseAdr.ft232_slave;
  59.     foreach(ch; msg) {
  60.         *usb_slave = ch;
  61.     }
  62. }
  63.  
  64. // If passing `SneakyString` as a parameter didn't work, passing integers might
  65. // actually be /not that bad/, given that such variables will not compile
  66. // when subjected to foreach loops, indexing, .length, and other array-like
  67. // or string-like operations. Thankfully, this makes mistakes unlikely.
  68. // Furthermore, as mentioned above, we can alias `ulong` into a different
  69. // type, which is called `string_u64` in this example. This alias lets us
  70. // document the intent of the parameter/variable without changing its
  71. // status as a primitive type.
  72. //
  73. // In the function below, I use the `SneakyString` union to convert the
  74. // `string_u64` integer into a `SneakyString` which can then do all of the
  75. // normal string-like things, largely thanks to the "alias str this"
  76. // statement in the union's body. Of course, there are many other was to
  77. // do the conversion, including the simple "cast(string)msg_u64" tactic,
  78. // or writing a dedicated-but-inline-able conversion function to centralize
  79. // the gunk.
  80. //
  81. // This one's probably kinda weak, but maybe it will give you ideas.
  82. //
  83. void write_to_host_SL02(string_u64  msg_u64) {
  84.  
  85.     SneakyString msg = msg_u64;
  86.  
  87.     // a fixed address to get bytes to the host via usb
  88.     char *usb_slave = cast(char*)BaseAdr.ft232_slave;
  89.     foreach(ch; msg) {
  90.         *usb_slave = ch;
  91.     }
  92. }
RAW Paste Data